├── .github └── workflows │ └── go.yml ├── .travis.yml ├── CONTRIBUTING.md ├── CONTRIBUTORS_GUIDE.md ├── LICENSE ├── README.md ├── SECURITY.md ├── alert.go ├── auth.go ├── auth_test.go ├── cache.go ├── cache_test.go ├── cipher_suites.go ├── common.go ├── common_string.go ├── conn.go ├── conn_test.go ├── defaults.go ├── dicttls ├── LICENSE ├── README.md ├── alerts.go ├── authorization_data_formats.go ├── cachedinformationtype_values.go ├── certificate_compression_algorithm_ids.go ├── certificate_status_types.go ├── certificte_types.go ├── cipher_suites.go ├── clientcertificatetype_identifiers.go ├── comp_meth_ids.go ├── contenttype.go ├── ec_curve_types.go ├── ec_point_formats.go ├── exttype_values.go ├── handshaketype.go ├── hashalgorithm.go ├── heartbeat_message_types.go ├── heartbeat_mode.go ├── hpke_aead_identifiers.go ├── hpke_kdf_identifiers.go ├── hpke_kem_identifiers.go ├── psk_key_exchange_mode.go ├── quic_frame_types.go ├── quic_transport_error_codes.go ├── quic_transport_parameters.go ├── signaturealgorithm.go ├── signaturescheme.go ├── supplemental_data_formats.go ├── supported_groups.go └── usermappingtype_values.go ├── ech.go ├── ech_test.go ├── example_test.go ├── examples ├── ech │ └── main.go ├── old │ └── examples.go └── tls-resumption │ └── main.go ├── fipsonly ├── fipsonly.go └── fipsonly_test.go ├── generate_cert.go ├── go.mod ├── go.sum ├── handshake_client.go ├── handshake_client_test.go ├── handshake_client_tls13.go ├── handshake_messages.go ├── handshake_messages_test.go ├── handshake_server.go ├── handshake_server_test.go ├── handshake_server_tls13.go ├── handshake_test.go ├── handshake_unix_test.go ├── internal ├── boring │ └── notboring.go ├── byteorder │ └── byteorder.go ├── fips140tls │ └── fipstls.go ├── helper │ └── typeconv.go ├── hkdf │ └── hkdf.go ├── hpke │ └── hpke.go ├── quicvarint │ ├── protocol │ │ └── protocol.go │ └── varint.go ├── tls12 │ └── tls12.go └── tls13 │ ├── tls13.go │ └── u_tls13.go ├── key_agreement.go ├── key_schedule.go ├── key_schedule_test.go ├── link_test.go ├── logo.png ├── logo_small.png ├── prf.go ├── prf_test.go ├── quic.go ├── quic_test.go ├── testdata ├── Client-TLSv10-ClientCert-ECDSA-ECDSA ├── Client-TLSv10-ClientCert-ECDSA-RSA ├── Client-TLSv10-ClientCert-Ed25519 ├── Client-TLSv10-ClientCert-RSA-ECDSA ├── Client-TLSv10-ClientCert-RSA-RSA ├── Client-TLSv10-ECDHE-ECDSA-AES ├── Client-TLSv10-ECDHE-RSA-AES ├── Client-TLSv10-Ed25519 ├── Client-TLSv10-ExportKeyingMaterial ├── Client-TLSv10-RSA-RC4 ├── Client-TLSv11-ECDHE-ECDSA-AES ├── Client-TLSv11-ECDHE-RSA-AES ├── Client-TLSv11-Ed25519 ├── Client-TLSv11-RSA-RC4 ├── Client-TLSv12-AES128-GCM-SHA256 ├── Client-TLSv12-AES128-SHA256 ├── Client-TLSv12-AES256-GCM-SHA384 ├── Client-TLSv12-ALPN ├── Client-TLSv12-ALPN-NoMatch ├── Client-TLSv12-ClientCert-ECDSA-ECDSA ├── Client-TLSv12-ClientCert-ECDSA-RSA ├── Client-TLSv12-ClientCert-Ed25519 ├── Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 ├── Client-TLSv12-ClientCert-RSA-ECDSA ├── Client-TLSv12-ClientCert-RSA-RSA ├── Client-TLSv12-ClientCert-RSA-RSAPKCS1v15 ├── Client-TLSv12-ClientCert-RSA-RSAPSS ├── Client-TLSv12-ECDHE-ECDSA-AES ├── Client-TLSv12-ECDHE-ECDSA-AES-GCM ├── Client-TLSv12-ECDHE-ECDSA-AES128-SHA256 ├── Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 ├── Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305 ├── Client-TLSv12-ECDHE-RSA-AES ├── Client-TLSv12-ECDHE-RSA-AES128-SHA256 ├── Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305 ├── Client-TLSv12-Ed25519 ├── Client-TLSv12-ExportKeyingMaterial ├── Client-TLSv12-P256-ECDHE ├── Client-TLSv12-RSA-RC4 ├── Client-TLSv12-RenegotiateOnce ├── Client-TLSv12-RenegotiateTwice ├── Client-TLSv12-RenegotiateTwiceRejected ├── Client-TLSv12-RenegotiationRejected ├── Client-TLSv12-SCT ├── Client-TLSv12-UTLS-AES128-GCM-SHA256-Chrome-58 ├── Client-TLSv12-UTLS-AES128-GCM-SHA256-Chrome-70 ├── Client-TLSv12-UTLS-AES128-GCM-SHA256-Firefox-55 ├── Client-TLSv12-UTLS-AES128-GCM-SHA256-Golang-0 ├── Client-TLSv12-UTLS-ECDHE-ECDSA-AES128-GCM-SHA256-Chrome-58 ├── Client-TLSv12-UTLS-ECDHE-ECDSA-AES128-GCM-SHA256-Chrome-58setclienthello ├── Client-TLSv12-UTLS-ECDHE-ECDSA-AES128-GCM-SHA256-Chrome-70 ├── Client-TLSv12-UTLS-ECDHE-ECDSA-AES128-GCM-SHA256-Firefox-55 ├── Client-TLSv12-UTLS-ECDHE-ECDSA-AES128-GCM-SHA256-Firefox-63 ├── Client-TLSv12-UTLS-ECDHE-ECDSA-AES128-GCM-SHA256-Golang-0 ├── Client-TLSv12-UTLS-ECDHE-ECDSA-AES128-SHA-Firefox-55 ├── Client-TLSv12-UTLS-ECDHE-ECDSA-AES128-SHA-Firefox-63 ├── Client-TLSv12-UTLS-ECDHE-ECDSA-AES128-SHA-Golang-0 ├── Client-TLSv12-UTLS-ECDHE-ECDSA-AES256-GCM-SHA256-Chrome-70 ├── Client-TLSv12-UTLS-ECDHE-ECDSA-AES256-SHA-Firefox-55 ├── Client-TLSv12-UTLS-ECDHE-ECDSA-AES256-SHA-Firefox-63 ├── Client-TLSv12-UTLS-ECDHE-ECDSA-AES256-SHA-Golang-0 ├── Client-TLSv12-UTLS-ECDHE-ECDSA-CHACHA20-POLY1305-Firefox-55 ├── Client-TLSv12-UTLS-ECDHE-ECDSA-CHACHA20-POLY1305-Firefox-63 ├── Client-TLSv12-UTLS-ECDHE-ECDSA-CHACHA20-POLY1305-Golang-0 ├── Client-TLSv12-UTLS-ECDHE-RSA-AES128-GCM-SHA256-Chrome-58 ├── Client-TLSv12-UTLS-ECDHE-RSA-AES128-GCM-SHA256-Chrome-58-fingerprinted ├── Client-TLSv12-UTLS-ECDHE-RSA-AES128-GCM-SHA256-Chrome-58setclienthello ├── Client-TLSv12-UTLS-ECDHE-RSA-AES128-GCM-SHA256-Chrome-70 ├── Client-TLSv12-UTLS-ECDHE-RSA-AES128-GCM-SHA256-Chrome-70-EmptyServerName ├── Client-TLSv12-UTLS-ECDHE-RSA-AES128-GCM-SHA256-Chrome-70-OmitSNI ├── Client-TLSv12-UTLS-ECDHE-RSA-AES128-GCM-SHA256-Chrome-70-ServerNameIP ├── Client-TLSv12-UTLS-ECDHE-RSA-AES128-GCM-SHA256-Firefox-55 ├── Client-TLSv12-UTLS-ECDHE-RSA-AES128-GCM-SHA256-Firefox-63 ├── Client-TLSv12-UTLS-ECDHE-RSA-AES128-GCM-SHA256-Golang-0 ├── Client-TLSv12-UTLS-ECDHE-RSA-AES128-SHA-Chrome-58 ├── Client-TLSv12-UTLS-ECDHE-RSA-AES128-SHA-Chrome-70 ├── Client-TLSv12-UTLS-ECDHE-RSA-AES128-SHA-Firefox-55 ├── Client-TLSv12-UTLS-ECDHE-RSA-AES128-SHA-Firefox-63 ├── Client-TLSv12-UTLS-ECDHE-RSA-AES128-SHA-Golang-0 ├── Client-TLSv12-UTLS-ECDHE-RSA-AES256-SHA-Chrome-58 ├── Client-TLSv12-UTLS-ECDHE-RSA-AES256-SHA-Chrome-70 ├── Client-TLSv12-UTLS-ECDHE-RSA-AES256-SHA-Firefox-55 ├── Client-TLSv12-UTLS-ECDHE-RSA-AES256-SHA-Firefox-63 ├── Client-TLSv12-UTLS-ECDHE-RSA-AES256-SHA-Golang-0 ├── Client-TLSv12-UTLS-ECDHE-RSA-CHACHA20-POLY1305-Chrome-58 ├── Client-TLSv12-UTLS-ECDHE-RSA-CHACHA20-POLY1305-Chrome-70 ├── Client-TLSv12-UTLS-ECDHE-RSA-CHACHA20-POLY1305-Firefox-55 ├── Client-TLSv12-UTLS-ECDHE-RSA-CHACHA20-POLY1305-Firefox-63 ├── Client-TLSv12-UTLS-ECDHE-RSA-CHACHA20-POLY1305-Golang-0 ├── Client-TLSv12-UTLS-setclienthello-ECDHE-RSA-AES128-GCM-SHA256-Chrome-58 ├── Client-TLSv12-X25519-ECDHE ├── Client-TLSv13-AES128-SHA256 ├── Client-TLSv13-AES256-SHA384 ├── Client-TLSv13-ALPN ├── Client-TLSv13-CHACHA20-SHA256 ├── Client-TLSv13-ClientCert-ECDSA-RSA ├── Client-TLSv13-ClientCert-Ed25519 ├── Client-TLSv13-ClientCert-RSA-ECDSA ├── Client-TLSv13-ClientCert-RSA-RSAPSS ├── Client-TLSv13-ECDSA ├── Client-TLSv13-Ed25519 ├── Client-TLSv13-ExportKeyingMaterial ├── Client-TLSv13-HelloRetryRequest ├── Client-TLSv13-KeyUpdate ├── Client-TLSv13-P256-ECDHE ├── Client-TLSv13-UTLS-HelloRetryRequest-Chrome-70 ├── Client-TLSv13-UTLS-TLS_AES_128_GCM_SHA256-Chrome-70 ├── Client-TLSv13-UTLS-TLS_AES_128_GCM_SHA256-Chrome-70-fingerprinted ├── Client-TLSv13-UTLS-TLS_AES_128_GCM_SHA256-Firefox-63 ├── Client-TLSv13-UTLS-TLS_AES_128_GCM_SHA256-raw-capture-fingerprinted ├── Client-TLSv13-UTLS-TLS_AES_256_GCM_SHA384-Chrome-70 ├── Client-TLSv13-UTLS-TLS_AES_256_GCM_SHA384-Firefox-63 ├── Client-TLSv13-UTLS-TLS_CHACHA20_POLY1305_SHA256-Chrome-70 ├── Client-TLSv13-UTLS-TLS_CHACHA20_POLY1305_SHA256-Firefox-63 ├── Client-TLSv13-X25519-ECDHE ├── ClientHello-JSON-Chrome102.json ├── ClientHello-JSON-Edge106.json ├── ClientHello-JSON-Firefox105.json ├── ClientHello-JSON-iOS14.json ├── Server-TLSv10-ECDHE-ECDSA-AES ├── Server-TLSv10-ExportKeyingMaterial ├── Server-TLSv10-RSA-3DES ├── Server-TLSv10-RSA-AES ├── Server-TLSv10-RSA-RC4 ├── Server-TLSv11-FallbackSCSV ├── Server-TLSv11-RSA-RC4 ├── Server-TLSv12-ALPN ├── Server-TLSv12-ALPN-Fallback ├── Server-TLSv12-ALPN-NoMatch ├── Server-TLSv12-ALPN-NotConfigured ├── Server-TLSv12-ClientAuthRequestedAndECDSAGiven ├── Server-TLSv12-ClientAuthRequestedAndEd25519Given ├── Server-TLSv12-ClientAuthRequestedAndGiven ├── Server-TLSv12-ClientAuthRequestedAndPKCS1v15Given ├── Server-TLSv12-ClientAuthRequestedNotGiven ├── Server-TLSv12-ECDHE-ECDSA-AES ├── Server-TLSv12-Ed25519 ├── Server-TLSv12-ExportKeyingMaterial ├── Server-TLSv12-IssueTicket ├── Server-TLSv12-IssueTicketPreDisable ├── Server-TLSv12-P256 ├── Server-TLSv12-RSA-3DES ├── Server-TLSv12-RSA-AES ├── Server-TLSv12-RSA-AES-GCM ├── Server-TLSv12-RSA-AES256-GCM-SHA384 ├── Server-TLSv12-RSA-RC4 ├── Server-TLSv12-RSA-RSAPKCS1v15 ├── Server-TLSv12-RSA-RSAPSS ├── Server-TLSv12-Resume ├── Server-TLSv12-ResumeDisabled ├── Server-TLSv12-SNI ├── Server-TLSv12-SNI-GetCertificate ├── Server-TLSv12-SNI-GetCertificateNotFound ├── Server-TLSv12-X25519 ├── Server-TLSv13-AES128-SHA256 ├── Server-TLSv13-AES256-SHA384 ├── Server-TLSv13-ALPN ├── Server-TLSv13-ALPN-Fallback ├── Server-TLSv13-ALPN-NoMatch ├── Server-TLSv13-ALPN-NotConfigured ├── Server-TLSv13-CHACHA20-SHA256 ├── Server-TLSv13-ClientAuthRequestedAndECDSAGiven ├── Server-TLSv13-ClientAuthRequestedAndEd25519Given ├── Server-TLSv13-ClientAuthRequestedAndGiven ├── Server-TLSv13-ClientAuthRequestedNotGiven ├── Server-TLSv13-ECDHE-ECDSA-AES ├── Server-TLSv13-Ed25519 ├── Server-TLSv13-ExportKeyingMaterial ├── Server-TLSv13-HelloRetryRequest ├── Server-TLSv13-IssueTicket ├── Server-TLSv13-IssueTicketPreDisable ├── Server-TLSv13-KeySharePreference ├── Server-TLSv13-P256 ├── Server-TLSv13-RSA-RSAPSS ├── Server-TLSv13-RSA-RSAPSS-TooSmall ├── Server-TLSv13-Resume ├── Server-TLSv13-Resume-HelloRetryRequest ├── Server-TLSv13-ResumeDisabled ├── Server-TLSv13-X25519 ├── example-cert.pem └── example-key.pem ├── testenv ├── testenv.go ├── testenv_cgo.go ├── testenv_notunix.go ├── testenv_notwin.go ├── testenv_unix.go └── testenv_windows.go ├── ticket.go ├── ticket_test.go ├── tls.go ├── tls_cf.go ├── tls_test.go ├── u_alias.go ├── u_clienthello_json.go ├── u_clienthello_json_test.go ├── u_common.go ├── u_common_test.go ├── u_conn.go ├── u_conn_test.go ├── u_ech.go ├── u_ech_config.go ├── u_ech_test.go ├── u_fingerprinter.go ├── u_fingerprinter_test.go ├── u_handshake_client.go ├── u_handshake_messages.go ├── u_hpke.go ├── u_key_schedule.go ├── u_parrots.go ├── u_pre_shared_key.go ├── u_prng.go ├── u_public.go ├── u_quic.go ├── u_quic_transport_parameters.go ├── u_quic_transport_parameters_test.go ├── u_roller.go ├── u_session_controller.go ├── u_session_ticket.go └── u_tls_extensions.go /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a golang project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go 3 | 4 | name: "Go" 5 | 6 | on: 7 | push: 8 | branches: ["master"] 9 | pull_request: 10 | branches: ["master"] 11 | 12 | jobs: 13 | build: 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | os: ["ubuntu-latest", "windows-latest", "macos-latest"] 18 | go: ["1.24.x"] 19 | runs-on: ${{ matrix.os }} 20 | steps: 21 | - uses: actions/checkout@v3 22 | - uses: actions/setup-go@v4 23 | with: 24 | go-version: ${{ matrix.go }} 25 | - run: go version 26 | - name: Build 27 | run: go build -v ./... 28 | - name: Test 29 | run: go test -v ./... 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - "1.11.x" 5 | 6 | sudo: required 7 | dist: trusty 8 | 9 | install: 10 | - go get -t ./... 11 | - go get golang.org/x/lint/golint 12 | # Install gometalinter 13 | - go get github.com/alecthomas/gometalinter 14 | 15 | script: 16 | - go test -race -v . 17 | - gometalinter --install 18 | - gometalinter --disable-all -E vet -E ineffassign --tests . 19 | - gometalinter --disable-all -E gofmt -E misspell -E goimports --tests u_* 20 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution, 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. -------------------------------------------------------------------------------- /CONTRIBUTORS_GUIDE.md: -------------------------------------------------------------------------------- 1 | # How this package works 2 | ### Chapter 1: [Making private things public](./u_public.go) 3 | There are numerous handshake-related structs in crypto/tls, most of which are either private or have private fields. 4 | One of them — `clientHandshakeState` — has private function `handshake()`, 5 | which is called in the beginning of default handshake. 6 | Unfortunately, user will not be able to directly access this struct outside of tls package. 7 | As a result, we decided to employ following workaround: declare public copies of private structs. 8 | Now user is free to manipulate fields of public `ClientHandshakeState`. 9 | Then, right before handshake, we can shallow-copy public state into private `clientHandshakeState`, 10 | call `handshake()` on it and carry on with default Golang handshake process. 11 | After handshake is done we shallow-copy private state back to public, allowing user to read results of handshake. 12 | 13 | ### Chapter 2: [TLSExtension](./u_tls_extensions.go) 14 | The way we achieve reasonable flexibilty with extensions is inspired by 15 | [ztls'](https://github.com/zmap/zcrypto/blob/master/tls/handshake_extensions.go) design. 16 | However, our design has several differences, so we wrote it from scratch. 17 | This design allows us to have an array of `TLSExtension` objects and then marshal them in order: 18 | ```Golang 19 | type TLSExtension interface { 20 | writeToUConn(*UConn) error 21 | 22 | Len() int // includes header 23 | 24 | // Read reads up to len(p) bytes into p. 25 | // It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. 26 | Read(p []byte) (n int, err error) // implements io.Reader 27 | } 28 | ``` 29 | `writeToUConn()` applies appropriate per-extension changes to `UConn`. 30 | 31 | `Len()` provides the size of marshaled extension, so we can allocate appropriate buffer beforehand, 32 | catch out-of-bound errors easily and guide size-dependent extensions such as padding. 33 | 34 | `Read(buffer []byte)` _writes(see: io.Reader interface)_ marshaled extensions into provided buffer. 35 | This avoids extra allocations. 36 | 37 | ### Chapter 3: [UConn](./u_conn.go) 38 | `UConn` extends standard `tls.Conn`. Most notably, it stores slice with `TLSExtension`s and public 39 | `ClientHandshakeState`. 40 | Whenever `UConn.BuildHandshakeState()` gets called (happens automatically in `UConn.Handshake()` 41 | or could be called manually), config will be applied according to chosen `ClientHelloID`. 42 | From contributor's view there are 2 main behaviors: 43 | * `HelloGolang` simply calls default Golang's [`makeClientHello()`](./handshake_client.go) 44 | and directly stores it into `HandshakeState.Hello`. utls-specific stuff is ignored. 45 | * Other ClientHelloIDs fill `UConn.Hello.{Random, CipherSuites, CompressionMethods}` and `UConn.Extensions` with 46 | per-parrot setup, which then gets applied to appropriate standard tls structs, 47 | and then marshaled by utls into `HandshakeState.Hello`. 48 | 49 | ### Chapter 4: Tests 50 | 51 | Tests exist, but coverage is very limited. What's covered is a conjunction of 52 | * TLS 1.2 53 | * Working parrots without any unsupported extensions (only Android 5.1 at this time) 54 | * Ciphersuites offered by parrot. 55 | * Ciphersuites supported by Golang 56 | * Simple conversation with reference implementation of OpenSSL. 57 | (e.g. no automatic checks for renegotiations, parroting quality and such) 58 | 59 | plus we test some other minor things. 60 | Basically, current tests aim to provide a sanity check. 61 | 62 | # Merging upstream 63 | ```Bash 64 | git remote add -f golang git@github.com:golang/go.git 65 | git checkout -b golang-upstream golang/master 66 | git subtree split -P src/crypto/tls/ -b golang-tls-upstream 67 | git checkout master 68 | git merge --no-commit golang-tls-upstream 69 | ``` 70 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | We will only maintain one branch which is the master branch. Unless otherwise requested, no security patches will be applied to older Major/Minor versions. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | For a vulnerability of low to no severity, which causing no threats to security, you may report it openly to us by [opening an issue](https://github.com/refraction-networking/utls/issues/new) 10 | 11 | If the vulnerability you are reporting inflicts some security impact, please [do so privately](https://github.com/refraction-networking/utls/security/advisories/new). 12 | -------------------------------------------------------------------------------- /alert.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. 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 "strconv" 8 | 9 | // An AlertError is a TLS alert. 10 | // 11 | // When using a QUIC transport, QUICConn methods will return an error 12 | // which wraps AlertError rather than sending a TLS alert. 13 | type AlertError uint8 14 | 15 | func (e AlertError) Error() string { 16 | return alert(e).String() 17 | } 18 | 19 | type alert uint8 20 | 21 | const ( 22 | // alert level 23 | alertLevelWarning = 1 24 | alertLevelError = 2 25 | ) 26 | 27 | const ( 28 | alertCloseNotify alert = 0 29 | alertUnexpectedMessage alert = 10 30 | alertBadRecordMAC alert = 20 31 | alertDecryptionFailed alert = 21 32 | alertRecordOverflow alert = 22 33 | alertDecompressionFailure alert = 30 34 | alertHandshakeFailure alert = 40 35 | alertBadCertificate alert = 42 36 | alertUnsupportedCertificate alert = 43 37 | alertCertificateRevoked alert = 44 38 | alertCertificateExpired alert = 45 39 | alertCertificateUnknown alert = 46 40 | alertIllegalParameter alert = 47 41 | alertUnknownCA alert = 48 42 | alertAccessDenied alert = 49 43 | alertDecodeError alert = 50 44 | alertDecryptError alert = 51 45 | alertExportRestriction alert = 60 46 | alertProtocolVersion alert = 70 47 | alertInsufficientSecurity alert = 71 48 | alertInternalError alert = 80 49 | alertInappropriateFallback alert = 86 50 | alertUserCanceled alert = 90 51 | alertNoRenegotiation alert = 100 52 | alertMissingExtension alert = 109 53 | alertUnsupportedExtension alert = 110 54 | alertCertificateUnobtainable alert = 111 55 | alertUnrecognizedName alert = 112 56 | alertBadCertificateStatusResponse alert = 113 57 | alertBadCertificateHashValue alert = 114 58 | alertUnknownPSKIdentity alert = 115 59 | alertCertificateRequired alert = 116 60 | alertNoApplicationProtocol alert = 120 61 | alertECHRequired alert = 121 62 | ) 63 | 64 | var alertText = map[alert]string{ 65 | alertCloseNotify: "close notify", 66 | alertUnexpectedMessage: "unexpected message", 67 | alertBadRecordMAC: "bad record MAC", 68 | alertDecryptionFailed: "decryption failed", 69 | alertRecordOverflow: "record overflow", 70 | alertDecompressionFailure: "decompression failure", 71 | alertHandshakeFailure: "handshake failure", 72 | alertBadCertificate: "bad certificate", 73 | alertUnsupportedCertificate: "unsupported certificate", 74 | alertCertificateRevoked: "revoked certificate", 75 | alertCertificateExpired: "expired certificate", 76 | alertCertificateUnknown: "unknown certificate", 77 | alertIllegalParameter: "illegal parameter", 78 | alertUnknownCA: "unknown certificate authority", 79 | alertAccessDenied: "access denied", 80 | alertDecodeError: "error decoding message", 81 | alertDecryptError: "error decrypting message", 82 | alertExportRestriction: "export restriction", 83 | alertProtocolVersion: "protocol version not supported", 84 | alertInsufficientSecurity: "insufficient security level", 85 | alertInternalError: "internal error", 86 | alertInappropriateFallback: "inappropriate fallback", 87 | alertUserCanceled: "user canceled", 88 | alertNoRenegotiation: "no renegotiation", 89 | alertMissingExtension: "missing extension", 90 | alertUnsupportedExtension: "unsupported extension", 91 | alertCertificateUnobtainable: "certificate unobtainable", 92 | alertUnrecognizedName: "unrecognized name", 93 | alertBadCertificateStatusResponse: "bad certificate status response", 94 | alertBadCertificateHashValue: "bad certificate hash value", 95 | alertUnknownPSKIdentity: "unknown PSK identity", 96 | alertCertificateRequired: "certificate required", 97 | alertNoApplicationProtocol: "no application protocol", 98 | alertECHRequired: "encrypted client hello required", 99 | } 100 | 101 | func (e alert) String() string { 102 | s, ok := alertText[e] 103 | if ok { 104 | return "tls: " + s 105 | } 106 | return "tls: alert(" + strconv.Itoa(int(e)) + ")" 107 | } 108 | 109 | func (e alert) Error() string { 110 | return e.String() 111 | } 112 | -------------------------------------------------------------------------------- /cache.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Go Authors. 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/x509" 9 | "runtime" 10 | "sync" 11 | "sync/atomic" 12 | ) 13 | 14 | type cacheEntry struct { 15 | refs atomic.Int64 16 | cert *x509.Certificate 17 | } 18 | 19 | // certCache implements an intern table for reference counted x509.Certificates, 20 | // implemented in a similar fashion to BoringSSL's CRYPTO_BUFFER_POOL. This 21 | // allows for a single x509.Certificate to be kept in memory and referenced from 22 | // multiple Conns. Returned references should not be mutated by callers. Certificates 23 | // are still safe to use after they are removed from the cache. 24 | // 25 | // Certificates are returned wrapped in an activeCert struct that should be held by 26 | // the caller. When references to the activeCert are freed, the number of references 27 | // to the certificate in the cache is decremented. Once the number of references 28 | // reaches zero, the entry is evicted from the cache. 29 | // 30 | // The main difference between this implementation and CRYPTO_BUFFER_POOL is that 31 | // CRYPTO_BUFFER_POOL is a more generic structure which supports blobs of data, 32 | // rather than specific structures. Since we only care about x509.Certificates, 33 | // certCache is implemented as a specific cache, rather than a generic one. 34 | // 35 | // See https://boringssl.googlesource.com/boringssl/+/master/include/openssl/pool.h 36 | // and https://boringssl.googlesource.com/boringssl/+/master/crypto/pool/pool.c 37 | // for the BoringSSL reference. 38 | type certCache struct { 39 | sync.Map 40 | } 41 | 42 | var globalCertCache = new(certCache) 43 | 44 | // activeCert is a handle to a certificate held in the cache. Once there are 45 | // no alive activeCerts for a given certificate, the certificate is removed 46 | // from the cache by a finalizer. 47 | type activeCert struct { 48 | cert *x509.Certificate 49 | } 50 | 51 | // active increments the number of references to the entry, wraps the 52 | // certificate in the entry in an activeCert, and sets the finalizer. 53 | // 54 | // Note that there is a race between active and the finalizer set on the 55 | // returned activeCert, triggered if active is called after the ref count is 56 | // decremented such that refs may be > 0 when evict is called. We consider this 57 | // safe, since the caller holding an activeCert for an entry that is no longer 58 | // in the cache is fine, with the only side effect being the memory overhead of 59 | // there being more than one distinct reference to a certificate alive at once. 60 | func (cc *certCache) active(e *cacheEntry) *activeCert { 61 | e.refs.Add(1) 62 | a := &activeCert{e.cert} 63 | runtime.SetFinalizer(a, func(_ *activeCert) { 64 | if e.refs.Add(-1) == 0 { 65 | cc.evict(e) 66 | } 67 | }) 68 | return a 69 | } 70 | 71 | // evict removes a cacheEntry from the cache. 72 | func (cc *certCache) evict(e *cacheEntry) { 73 | cc.Delete(string(e.cert.Raw)) 74 | } 75 | 76 | // newCert returns a x509.Certificate parsed from der. If there is already a copy 77 | // of the certificate in the cache, a reference to the existing certificate will 78 | // be returned. Otherwise, a fresh certificate will be added to the cache, and 79 | // the reference returned. The returned reference should not be mutated. 80 | func (cc *certCache) newCert(der []byte) (*activeCert, error) { 81 | if entry, ok := cc.Load(string(der)); ok { 82 | return cc.active(entry.(*cacheEntry)), nil 83 | } 84 | 85 | cert, err := x509.ParseCertificate(der) 86 | if err != nil { 87 | return nil, err 88 | } 89 | 90 | entry := &cacheEntry{cert: cert} 91 | if entry, loaded := cc.LoadOrStore(string(der), entry); loaded { 92 | return cc.active(entry.(*cacheEntry)), nil 93 | } 94 | return cc.active(entry), nil 95 | } 96 | -------------------------------------------------------------------------------- /cache_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Go Authors. 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 | "encoding/pem" 9 | "fmt" 10 | "runtime" 11 | "testing" 12 | "time" 13 | ) 14 | 15 | func TestCertCache(t *testing.T) { 16 | cc := certCache{} 17 | p, _ := pem.Decode([]byte(rsaCertPEM)) 18 | if p == nil { 19 | t.Fatal("Failed to decode certificate") 20 | } 21 | 22 | certA, err := cc.newCert(p.Bytes) 23 | if err != nil { 24 | t.Fatalf("newCert failed: %s", err) 25 | } 26 | certB, err := cc.newCert(p.Bytes) 27 | if err != nil { 28 | t.Fatalf("newCert failed: %s", err) 29 | } 30 | if certA.cert != certB.cert { 31 | t.Fatal("newCert returned a unique reference for a duplicate certificate") 32 | } 33 | 34 | if entry, ok := cc.Load(string(p.Bytes)); !ok { 35 | t.Fatal("cache does not contain expected entry") 36 | } else { 37 | if refs := entry.(*cacheEntry).refs.Load(); refs != 2 { 38 | t.Fatalf("unexpected number of references: got %d, want 2", refs) 39 | } 40 | } 41 | 42 | timeoutRefCheck := func(t *testing.T, key string, count int64) { 43 | t.Helper() 44 | c := time.After(4 * time.Second) 45 | for { 46 | select { 47 | case <-c: 48 | t.Fatal("timed out waiting for expected ref count") 49 | default: 50 | e, ok := cc.Load(key) 51 | if !ok && count != 0 { 52 | t.Fatal("cache does not contain expected key") 53 | } else if count == 0 && !ok { 54 | return 55 | } 56 | 57 | if e.(*cacheEntry).refs.Load() == count { 58 | return 59 | } 60 | } 61 | } 62 | } 63 | 64 | // Keep certA alive until at least now, so that we can 65 | // purposefully nil it and force the finalizer to be 66 | // called. 67 | runtime.KeepAlive(certA) 68 | certA = nil 69 | runtime.GC() 70 | 71 | timeoutRefCheck(t, string(p.Bytes), 1) 72 | 73 | // Keep certB alive until at least now, so that we can 74 | // purposefully nil it and force the finalizer to be 75 | // called. 76 | runtime.KeepAlive(certB) 77 | certB = nil 78 | runtime.GC() 79 | 80 | timeoutRefCheck(t, string(p.Bytes), 0) 81 | } 82 | 83 | func BenchmarkCertCache(b *testing.B) { 84 | p, _ := pem.Decode([]byte(rsaCertPEM)) 85 | if p == nil { 86 | b.Fatal("Failed to decode certificate") 87 | } 88 | 89 | cc := certCache{} 90 | b.ReportAllocs() 91 | b.ResetTimer() 92 | // We expect that calling newCert additional times after 93 | // the initial call should not cause additional allocations. 94 | for extra := 0; extra < 4; extra++ { 95 | b.Run(fmt.Sprint(extra), func(b *testing.B) { 96 | actives := make([]*activeCert, extra+1) 97 | b.ResetTimer() 98 | for i := 0; i < b.N; i++ { 99 | var err error 100 | actives[0], err = cc.newCert(p.Bytes) 101 | if err != nil { 102 | b.Fatal(err) 103 | } 104 | for j := 0; j < extra; j++ { 105 | actives[j+1], err = cc.newCert(p.Bytes) 106 | if err != nil { 107 | b.Fatal(err) 108 | } 109 | } 110 | for j := 0; j < extra+1; j++ { 111 | actives[j] = nil 112 | } 113 | runtime.GC() 114 | } 115 | }) 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /common_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -linecomment -type=SignatureScheme,CurveID,ClientAuthType -output=common_string.go"; DO NOT EDIT. 2 | 3 | package tls 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[PKCS1WithSHA256-1025] 12 | _ = x[PKCS1WithSHA384-1281] 13 | _ = x[PKCS1WithSHA512-1537] 14 | _ = x[PSSWithSHA256-2052] 15 | _ = x[PSSWithSHA384-2053] 16 | _ = x[PSSWithSHA512-2054] 17 | _ = x[ECDSAWithP256AndSHA256-1027] 18 | _ = x[ECDSAWithP384AndSHA384-1283] 19 | _ = x[ECDSAWithP521AndSHA512-1539] 20 | _ = x[Ed25519-2055] 21 | _ = x[PKCS1WithSHA1-513] 22 | _ = x[ECDSAWithSHA1-515] 23 | } 24 | 25 | const ( 26 | _SignatureScheme_name_0 = "PKCS1WithSHA1" 27 | _SignatureScheme_name_1 = "ECDSAWithSHA1" 28 | _SignatureScheme_name_2 = "PKCS1WithSHA256" 29 | _SignatureScheme_name_3 = "ECDSAWithP256AndSHA256" 30 | _SignatureScheme_name_4 = "PKCS1WithSHA384" 31 | _SignatureScheme_name_5 = "ECDSAWithP384AndSHA384" 32 | _SignatureScheme_name_6 = "PKCS1WithSHA512" 33 | _SignatureScheme_name_7 = "ECDSAWithP521AndSHA512" 34 | _SignatureScheme_name_8 = "PSSWithSHA256PSSWithSHA384PSSWithSHA512Ed25519" 35 | ) 36 | 37 | var ( 38 | _SignatureScheme_index_8 = [...]uint8{0, 13, 26, 39, 46} 39 | ) 40 | 41 | func (i SignatureScheme) String() string { 42 | switch { 43 | case i == 513: 44 | return _SignatureScheme_name_0 45 | case i == 515: 46 | return _SignatureScheme_name_1 47 | case i == 1025: 48 | return _SignatureScheme_name_2 49 | case i == 1027: 50 | return _SignatureScheme_name_3 51 | case i == 1281: 52 | return _SignatureScheme_name_4 53 | case i == 1283: 54 | return _SignatureScheme_name_5 55 | case i == 1537: 56 | return _SignatureScheme_name_6 57 | case i == 1539: 58 | return _SignatureScheme_name_7 59 | case 2052 <= i && i <= 2055: 60 | i -= 2052 61 | return _SignatureScheme_name_8[_SignatureScheme_index_8[i]:_SignatureScheme_index_8[i+1]] 62 | default: 63 | return "SignatureScheme(" + strconv.FormatInt(int64(i), 10) + ")" 64 | } 65 | } 66 | func _() { 67 | // An "invalid array index" compiler error signifies that the constant values have changed. 68 | // Re-run the stringer command to generate them again. 69 | var x [1]struct{} 70 | _ = x[CurveP256-23] 71 | _ = x[CurveP384-24] 72 | _ = x[CurveP521-25] 73 | _ = x[X25519-29] 74 | _ = x[X25519MLKEM768-4588] 75 | } 76 | 77 | const ( 78 | _CurveID_name_0 = "CurveP256CurveP384CurveP521" 79 | _CurveID_name_1 = "X25519" 80 | _CurveID_name_2 = "X25519MLKEM768" 81 | ) 82 | 83 | var ( 84 | _CurveID_index_0 = [...]uint8{0, 9, 18, 27} 85 | ) 86 | 87 | func (i CurveID) String() string { 88 | switch { 89 | case 23 <= i && i <= 25: 90 | i -= 23 91 | return _CurveID_name_0[_CurveID_index_0[i]:_CurveID_index_0[i+1]] 92 | case i == 29: 93 | return _CurveID_name_1 94 | case i == 4588: 95 | return _CurveID_name_2 96 | default: 97 | return "CurveID(" + strconv.FormatInt(int64(i), 10) + ")" 98 | } 99 | } 100 | func _() { 101 | // An "invalid array index" compiler error signifies that the constant values have changed. 102 | // Re-run the stringer command to generate them again. 103 | var x [1]struct{} 104 | _ = x[NoClientCert-0] 105 | _ = x[RequestClientCert-1] 106 | _ = x[RequireAnyClientCert-2] 107 | _ = x[VerifyClientCertIfGiven-3] 108 | _ = x[RequireAndVerifyClientCert-4] 109 | } 110 | 111 | const _ClientAuthType_name = "NoClientCertRequestClientCertRequireAnyClientCertVerifyClientCertIfGivenRequireAndVerifyClientCert" 112 | 113 | var _ClientAuthType_index = [...]uint8{0, 12, 29, 49, 72, 98} 114 | 115 | func (i ClientAuthType) String() string { 116 | if i < 0 || i >= ClientAuthType(len(_ClientAuthType_index)-1) { 117 | return "ClientAuthType(" + strconv.FormatInt(int64(i), 10) + ")" 118 | } 119 | return _ClientAuthType_name[_ClientAuthType_index[i]:_ClientAuthType_index[i+1]] 120 | } 121 | -------------------------------------------------------------------------------- /defaults.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. 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 | "slices" 9 | _ "unsafe" // for linkname 10 | ) 11 | 12 | // Defaults are collected in this file to allow distributions to more easily patch 13 | // them to apply local policies. 14 | 15 | // var tlsmlkem = godebug.New("tlsmlkem") [uTLS] 16 | 17 | // defaultCurvePreferences is the default set of supported key exchanges, as 18 | // well as the preference order. 19 | func defaultCurvePreferences() []CurveID { 20 | // [uTLS section begins] 21 | // if tlsmlkem.Value() == "0" { 22 | // return []CurveID{X25519, CurveP256, CurveP384, CurveP521} 23 | // } 24 | // [uTLS section ends] 25 | 26 | return []CurveID{X25519MLKEM768, X25519, CurveP256, CurveP384, CurveP521} 27 | } 28 | 29 | // defaultSupportedSignatureAlgorithms contains the signature and hash algorithms that 30 | // the code advertises as supported in a TLS 1.2+ ClientHello and in a TLS 1.2+ 31 | // CertificateRequest. The two fields are merged to match with TLS 1.3. 32 | // Note that in TLS 1.2, the ECDSA algorithms are not constrained to P-256, etc. 33 | var defaultSupportedSignatureAlgorithms = []SignatureScheme{ 34 | PSSWithSHA256, 35 | ECDSAWithP256AndSHA256, 36 | Ed25519, 37 | PSSWithSHA384, 38 | PSSWithSHA512, 39 | PKCS1WithSHA256, 40 | PKCS1WithSHA384, 41 | PKCS1WithSHA512, 42 | ECDSAWithP384AndSHA384, 43 | ECDSAWithP521AndSHA512, 44 | PKCS1WithSHA1, 45 | ECDSAWithSHA1, 46 | } 47 | 48 | // [uTLS section begins] 49 | // var tlsrsakex = godebug.New("tlsrsakex") 50 | // var tls3des = godebug.New("tls3des") 51 | // [uTLS section ends] 52 | 53 | func defaultCipherSuites() []uint16 { 54 | suites := slices.Clone(cipherSuitesPreferenceOrder) 55 | return slices.DeleteFunc(suites, func(c uint16) bool { 56 | return disabledCipherSuites[c] || 57 | // [uTLS section begins] 58 | // tlsrsakex.Value() != "1" && rsaKexCiphers[c] || 59 | // tls3des.Value() != "1" && tdesCiphers[c] 60 | rsaKexCiphers[c] || 61 | tdesCiphers[c] 62 | // [uTLS section ends] 63 | }) 64 | } 65 | 66 | // defaultCipherSuitesTLS13 is also the preference order, since there are no 67 | // disabled by default TLS 1.3 cipher suites. The same AES vs ChaCha20 logic as 68 | // cipherSuitesPreferenceOrder applies. 69 | // 70 | // defaultCipherSuitesTLS13 should be an internal detail, 71 | // but widely used packages access it using linkname. 72 | // Notable members of the hall of shame include: 73 | // - github.com/quic-go/quic-go 74 | // - github.com/sagernet/quic-go 75 | // 76 | // Do not remove or change the type signature. 77 | // See go.dev/issue/67401. 78 | // 79 | //go:linkname defaultCipherSuitesTLS13 80 | var defaultCipherSuitesTLS13 = []uint16{ 81 | TLS_AES_128_GCM_SHA256, 82 | TLS_AES_256_GCM_SHA384, 83 | TLS_CHACHA20_POLY1305_SHA256, 84 | } 85 | 86 | // defaultCipherSuitesTLS13NoAES should be an internal detail, 87 | // but widely used packages access it using linkname. 88 | // Notable members of the hall of shame include: 89 | // - github.com/quic-go/quic-go 90 | // - github.com/sagernet/quic-go 91 | // 92 | // Do not remove or change the type signature. 93 | // See go.dev/issue/67401. 94 | // 95 | //go:linkname defaultCipherSuitesTLS13NoAES 96 | var defaultCipherSuitesTLS13NoAES = []uint16{ 97 | TLS_CHACHA20_POLY1305_SHA256, 98 | TLS_AES_128_GCM_SHA256, 99 | TLS_AES_256_GCM_SHA384, 100 | } 101 | 102 | // The FIPS-only policies below match BoringSSL's 103 | // ssl_compliance_policy_fips_202205, which is based on NIST SP 800-52r2. 104 | // https://cs.opensource.google/boringssl/boringssl/+/master:ssl/ssl_lib.cc;l=3289;drc=ea7a88fa 105 | 106 | var defaultSupportedVersionsFIPS = []uint16{ 107 | VersionTLS12, 108 | VersionTLS13, 109 | } 110 | 111 | // defaultCurvePreferencesFIPS are the FIPS-allowed curves, 112 | // in preference order (most preferable first). 113 | var defaultCurvePreferencesFIPS = []CurveID{CurveP256, CurveP384} 114 | 115 | // defaultSupportedSignatureAlgorithmsFIPS currently are a subset of 116 | // defaultSupportedSignatureAlgorithms without Ed25519 and SHA-1. 117 | var defaultSupportedSignatureAlgorithmsFIPS = []SignatureScheme{ 118 | PSSWithSHA256, 119 | PSSWithSHA384, 120 | PSSWithSHA512, 121 | PKCS1WithSHA256, 122 | ECDSAWithP256AndSHA256, 123 | PKCS1WithSHA384, 124 | ECDSAWithP384AndSHA384, 125 | PKCS1WithSHA512, 126 | } 127 | 128 | // defaultCipherSuitesFIPS are the FIPS-allowed cipher suites. 129 | var defaultCipherSuitesFIPS = []uint16{ 130 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 131 | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 132 | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 133 | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 134 | } 135 | 136 | // defaultCipherSuitesTLS13FIPS are the FIPS-allowed cipher suites for TLS 1.3. 137 | var defaultCipherSuitesTLS13FIPS = []uint16{ 138 | TLS_AES_128_GCM_SHA256, 139 | TLS_AES_256_GCM_SHA384, 140 | } 141 | -------------------------------------------------------------------------------- /dicttls/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2023, Gaukas Wang 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /dicttls/README.md: -------------------------------------------------------------------------------- 1 | # Dict TLS 2 | 3 | This is a vendored version of [godicttls](https://github.com/gaukas/godicttls) 4 | 5 | Below is a copy of the original README.md 6 | 7 | # godicttls 8 | Dictionary for TLS written in Go providing bidirectional mapping values to their names, plus enum convenience for values. 9 | 10 | Last Update with data fetched from [IANA](www.iana.org) in March 2023: 11 | - Transport Layer Security (TLS) Parameters [link](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml) 12 | - Transport Layer Security (TLS) Extensions [link](https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml) -------------------------------------------------------------------------------- /dicttls/alerts.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-6 4 | // last updated: March 2023 5 | 6 | const ( 7 | Alert_close_notify uint8 = 0 8 | Alert_unexpected_message uint8 = 10 9 | Alert_bad_record_mac uint8 = 20 10 | Alert_decryption_failed uint8 = 21 11 | Alert_record_overflow uint8 = 22 12 | Alert_decompression_failure uint8 = 30 13 | Alert_handshake_failure uint8 = 40 14 | Alert_no_certificate uint8 = 41 15 | Alert_bad_certificate uint8 = 42 16 | Alert_unsupported_certificate uint8 = 43 17 | Alert_certificate_revoked uint8 = 44 18 | Alert_certificate_expired uint8 = 45 19 | Alert_certificate_unknown uint8 = 46 20 | Alert_illegal_parameter uint8 = 47 21 | Alert_unknown_ca uint8 = 48 22 | Alert_access_denied uint8 = 49 23 | Alert_decode_error uint8 = 50 24 | Alert_decrypt_error uint8 = 51 25 | Alert_too_many_cids_requested uint8 = 52 26 | Alert_export_restriction uint8 = 60 27 | Alert_protocol_version uint8 = 70 28 | Alert_insufficient_security uint8 = 71 29 | Alert_internal_error uint8 = 80 30 | Alert_inappropriate_fallback uint8 = 86 31 | Alert_user_canceled uint8 = 90 32 | Alert_no_renegotiation uint8 = 100 33 | Alert_missing_extension uint8 = 109 34 | Alert_unsupported_extension uint8 = 110 35 | Alert_certificate_unobtainable uint8 = 111 36 | Alert_unrecognized_name uint8 = 112 37 | Alert_bad_certificate_status_response uint8 = 113 38 | Alert_bad_certificate_hash_value uint8 = 114 39 | Alert_unknown_psk_identity uint8 = 115 40 | Alert_certificate_required uint8 = 116 41 | Alert_no_application_protocol uint8 = 120 42 | ) 43 | 44 | var DictAlertValueIndexed = map[uint8]string{ 45 | 0: "close_notify", 46 | 10: "unexpected_message", 47 | 20: "bad_record_mac", 48 | 21: "decryption_failed", 49 | 22: "record_overflow", 50 | 30: "decompression_failure", 51 | 40: "handshake_failure", 52 | 41: "no_certificate", 53 | 42: "bad_certificate", 54 | 43: "unsupported_certificate", 55 | 44: "certificate_revoked", 56 | 45: "certificate_expired", 57 | 46: "certificate_unknown", 58 | 47: "illegal_parameter", 59 | 48: "unknown_ca", 60 | 49: "access_denied", 61 | 50: "decode_error", 62 | 51: "decrypt_error", 63 | 52: "too_many_cids_requested", 64 | 60: "export_restriction", 65 | 70: "protocol_version", 66 | 71: "insufficient_security", 67 | 80: "internal_error", 68 | 86: "inappropriate_fallback", 69 | 90: "user_canceled", 70 | 100: "no_renegotiation", 71 | 109: "missing_extension", 72 | 110: "unsupported_extension", 73 | 111: "certificate_unobtainable", 74 | 112: "unrecognized_name", 75 | 113: "bad_certificate_status_response", 76 | 114: "bad_certificate_hash_value", 77 | 115: "unknown_psk_identity", 78 | 116: "certificate_required", 79 | 120: "no_application_protocol", 80 | } 81 | 82 | var DictAlertNameIndexed = map[string]uint8{ 83 | "close_notify": 0, 84 | "unexpected_message": 10, 85 | "bad_record_mac": 20, 86 | "decryption_failed": 21, 87 | "record_overflow": 22, 88 | "decompression_failure": 30, 89 | "handshake_failure": 40, 90 | "no_certificate": 41, 91 | "bad_certificate": 42, 92 | "unsupported_certificate": 43, 93 | "certificate_revoked": 44, 94 | "certificate_expired": 45, 95 | "certificate_unknown": 46, 96 | "illegal_parameter": 47, 97 | "unknown_ca": 48, 98 | "access_denied": 49, 99 | "decode_error": 50, 100 | "decrypt_error": 51, 101 | "too_many_cids_requested": 52, 102 | "export_restriction": 60, 103 | "protocol_version": 70, 104 | "insufficient_security": 71, 105 | "internal_error": 80, 106 | "inappropriate_fallback": 86, 107 | "user_canceled": 90, 108 | "no_renegotiation": 100, 109 | "missing_extension": 109, 110 | "unsupported_extension": 110, 111 | "certificate_unobtainable": 111, 112 | "unrecognized_name": 112, 113 | "bad_certificate_status_response": 113, 114 | "bad_certificate_hash_value": 114, 115 | "unknown_psk_identity": 115, 116 | "certificate_required": 116, 117 | "no_application_protocol": 120, 118 | } 119 | -------------------------------------------------------------------------------- /dicttls/authorization_data_formats.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#authorization-data 4 | // last updated: March 2023 5 | 6 | const ( 7 | AuthData_x509_attr_cert uint16 = 0 8 | AuthData_saml_assertion uint16 = 1 9 | AuthData_x509_attr_cert_url uint16 = 2 10 | AuthData_saml_assertion_url uint16 = 3 11 | AuthData_keynote_assertion_list uint16 = 64 12 | AuthData_keynote_assertion_list_url uint16 = 65 13 | AuthData_dtcp_authorization uint16 = 66 14 | ) 15 | 16 | var DictAuthorizationDataFormatValueIndexed = map[uint16]string{ 17 | 0: "x509_attr_cert", 18 | 1: "saml_assertion", 19 | 2: "x509_attr_cert_url", 20 | 3: "saml_assertion_url", 21 | 64: "keynote_assertion_list", 22 | 65: "keynote_assertion_list_url", 23 | 66: "dtcp_authorization", 24 | } 25 | 26 | var DictAuthorizationDataFormatNameIndexed = map[string]uint16{ 27 | "x509_attr_cert": 0, 28 | "saml_assertion": 1, 29 | "x509_attr_cert_url": 2, 30 | "saml_assertion_url": 3, 31 | "Unassigned": 0, 32 | "keynote_assertion_list": 64, 33 | "keynote_assertion_list_url": 65, 34 | "dtcp_authorization": 66, 35 | } 36 | -------------------------------------------------------------------------------- /dicttls/cachedinformationtype_values.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#cachedinformationtype 4 | // last updated: March 2023 5 | 6 | const ( 7 | CachedInformationType_cert uint8 = 1 8 | CachedInformationType_cert_req uint8 = 2 9 | ) 10 | 11 | var DictCachedInformationTypeValueIndexed = map[uint8]string{ 12 | 1: "cert", 13 | 2: "cert_req", 14 | } 15 | 16 | var DictCachedInformationTypeNameIndexed = map[string]uint8{ 17 | "cert": 1, 18 | "cert_req": 2, 19 | } 20 | -------------------------------------------------------------------------------- /dicttls/certificate_compression_algorithm_ids.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#tls-certificate-compression-algorithm-ids 4 | // last updated: March 2023 5 | 6 | const ( 7 | CertCompAlg_zlib uint16 = 1 8 | CertCompAlg_brotli uint16 = 2 9 | CertCompAlg_zstd uint16 = 3 10 | ) 11 | 12 | var DictCertificateCompressionAlgorithmValueIndexed = map[uint16]string{ 13 | 1: "zlib", 14 | 2: "brotli", 15 | 3: "zstd", 16 | } 17 | 18 | var DictCertificateCompressionAlgorithmNameIndexed = map[string]uint16{ 19 | "zlib": 1, 20 | "brotli": 2, 21 | "zstd": 3, 22 | } 23 | -------------------------------------------------------------------------------- /dicttls/certificate_status_types.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#certificate-status 4 | // last updated: March 2023 5 | 6 | const ( 7 | CertStatusType_ocsp uint8 = 1 8 | CertStatusType_ocsp_multi uint8 = 2 9 | ) 10 | 11 | var DictCertificateStatusTypeValueIndexed = map[uint8]string{ 12 | 1: "ocsp", 13 | 2: "ocsp_multi", 14 | } 15 | 16 | var DictCertificateStatusTypeNameIndexed = map[string]uint8{ 17 | "ocsp": 1, 18 | "ocsp_multi": 2, 19 | } 20 | -------------------------------------------------------------------------------- /dicttls/certificte_types.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#tls-extensiontype-values-3 4 | // last updated: March 2023 5 | 6 | const ( 7 | CertType_X509 uint8 = 0 8 | CertType_OpenPGP uint8 = 1 9 | CertType_Raw_Public_Key uint8 = 2 10 | CertType_1609Dot2 uint8 = 3 11 | ) 12 | 13 | var DictCertificateTypeValueIndexed = map[uint8]string{ 14 | 0: "X509", 15 | 1: "OpenPGP", 16 | 2: "Raw Public Key", 17 | 3: "1609Dot2", 18 | } 19 | 20 | var DictCertificateTypeNameIndexed = map[string]uint8{ 21 | "X509": 0, 22 | "OpenPGP": 1, 23 | "Raw Public Key": 2, 24 | "1609Dot2": 3, 25 | } 26 | -------------------------------------------------------------------------------- /dicttls/clientcertificatetype_identifiers.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-2 4 | // last updated: March 2023 5 | 6 | const ( 7 | ClientCertTypeIdentifier_rsa_sign uint8 = 1 8 | ClientCertTypeIdentifier_dss_sign uint8 = 2 9 | ClientCertTypeIdentifier_rsa_fixed_dh uint8 = 3 10 | ClientCertTypeIdentifier_dss_fixed_dh uint8 = 4 11 | ClientCertTypeIdentifier_rsa_ephemeral_dh uint8 = 5 12 | ClientCertTypeIdentifier_dss_ephemeral_dh uint8 = 6 13 | ClientCertTypeIdentifier_fortezza_dms uint8 = 20 14 | ClientCertTypeIdentifier_ecdsa_sign uint8 = 64 15 | ClientCertTypeIdentifier_rsa_fixed_ecdh uint8 = 65 16 | ClientCertTypeIdentifier_ecdsa_fixed_ecdh uint8 = 66 17 | ClientCertTypeIdentifier_gost_sign256 uint8 = 67 18 | ClientCertTypeIdentifier_gost_sign512 uint8 = 68 19 | ) 20 | 21 | var DictClientCertificateTypeIdentifierValueIndexed = map[uint8]string{ 22 | 1: "rsa_sign", 23 | 2: "dss_sign", 24 | 3: "rsa_fixed_dh", 25 | 4: "dss_fixed_dh", 26 | 5: "rsa_ephemeral_dh", 27 | 6: "dss_ephemeral_dh", 28 | 20: "fortezza_dms", 29 | 64: "ecdsa_sign", 30 | 65: "rsa_fixed_ecdh", 31 | 66: "ecdsa_fixed_ecdh", 32 | 67: "gost_sign256", 33 | 68: "gost_sign512", 34 | } 35 | 36 | var DictClientCertificateTypeIdentifierNameIndexed = map[string]uint8{ 37 | "rsa_sign": 1, 38 | "dss_sign": 2, 39 | "rsa_fixed_dh": 3, 40 | "dss_fixed_dh": 4, 41 | "rsa_ephemeral_dh": 5, 42 | "dss_ephemeral_dh": 6, 43 | "fortezza_dms": 20, 44 | "ecdsa_sign": 64, 45 | "rsa_fixed_ecdh": 65, 46 | "ecdsa_fixed_ecdh": 66, 47 | "gost_sign256": 67, 48 | "gost_sign512": 68, 49 | } 50 | -------------------------------------------------------------------------------- /dicttls/comp_meth_ids.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/comp-meth-ids/comp-meth-ids-2.csv 4 | // last updated: March 2023 5 | 6 | const ( 7 | CompMeth_NULL uint8 = 0 8 | CompMeth_DEFLATE uint8 = 1 9 | CompMeth_LZS uint8 = 64 10 | ) 11 | 12 | var DictCompMethValueIndexed = map[uint8]string{ 13 | 0: "NULL", 14 | 1: "DEFLATE", 15 | 64: "LZS", 16 | } 17 | 18 | var DictCompMethNameIndexed = map[string]uint8{ 19 | "NULL": 0, 20 | "DEFLATE": 1, 21 | "LZS": 64, 22 | } 23 | -------------------------------------------------------------------------------- /dicttls/contenttype.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-5 4 | // last updated: March 2023 5 | 6 | const ( 7 | ContentType_change_cipher_spec uint8 = 20 8 | ContentType_alert uint8 = 21 9 | ContentType_handshake uint8 = 22 10 | ContentType_application_data uint8 = 23 11 | ContentType_heartbeat uint8 = 24 12 | ContentType_tls12_cid uint8 = 25 13 | ContentType_ACK uint8 = 26 14 | ) 15 | 16 | var DictContentTypeValueIndexed = map[uint8]string{ 17 | 20: "change_cipher_spec", 18 | 21: "alert", 19 | 22: "handshake", 20 | 23: "application_data", 21 | 24: "heartbeat", 22 | 25: "tls12_cid", 23 | 26: "ACK", 24 | } 25 | 26 | var DictContentTypeNameIndexed = map[string]uint8{ 27 | "change_cipher_spec": 20, 28 | "alert": 21, 29 | "handshake": 22, 30 | "application_data": 23, 31 | "heartbeat": 24, 32 | "tls12_cid": 25, 33 | "ACK": 26, 34 | } 35 | -------------------------------------------------------------------------------- /dicttls/ec_curve_types.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-10 4 | // last updated: March 2023 5 | 6 | const ( 7 | ECCurve_explicit_prime uint16 = 1 8 | ECCurve_explicit_char2 uint16 = 2 9 | ECCurve_named_curve uint16 = 3 10 | ) 11 | 12 | var DictECCurveTypeValueIndexed = map[uint16]string{ 13 | 1: "explicit_prime", 14 | 2: "explicit_char2", 15 | 3: "named_curve", 16 | } 17 | 18 | var DictECCurveTypeNameIndexed = map[string]uint16{ 19 | "explicit_prime": 1, 20 | "explicit_char2": 2, 21 | "named_curve": 3, 22 | } 23 | -------------------------------------------------------------------------------- /dicttls/ec_point_formats.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-9 4 | // last updated: March 2023 5 | 6 | const ( 7 | ECPoint_uncompressed uint8 = 0 8 | ECPoint_ansiX962_compressed_prime uint8 = 1 9 | ECPoint_ansiX962_compressed_char2 uint8 = 2 10 | ) 11 | 12 | var DictECPointFormatValueIndexed = map[uint8]string{ 13 | 0: "uncompressed", 14 | 1: "ansiX962_compressed_prime", 15 | 2: "ansiX962_compressed_char2", 16 | } 17 | 18 | var DictECPointFormatNameIndexed = map[string]uint8{ 19 | "uncompressed": 0, 20 | "ansiX962_compressed_prime": 1, 21 | "ansiX962_compressed_char2": 2, 22 | } 23 | -------------------------------------------------------------------------------- /dicttls/handshaketype.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-7 4 | // last updated: March 2023 5 | 6 | const ( 7 | HandshakeType_hello_request uint8 = 0 8 | HandshakeType_client_hello uint8 = 1 9 | HandshakeType_server_hello uint8 = 2 10 | HandshakeType_hello_verify_request uint8 = 3 11 | HandshakeType_new_session_ticket uint8 = 4 12 | HandshakeType_end_of_early_data uint8 = 5 13 | HandshakeType_hello_retry_request uint8 = 6 14 | HandshakeType_encrypted_extensions uint8 = 8 15 | HandshakeType_request_connection_id uint8 = 9 16 | HandshakeType_new_connection_id uint8 = 10 17 | HandshakeType_certificate uint8 = 11 18 | HandshakeType_server_key_exchange uint8 = 12 19 | HandshakeType_certificate_request uint8 = 13 20 | HandshakeType_server_hello_done uint8 = 14 21 | HandshakeType_certificate_verify uint8 = 15 22 | HandshakeType_client_key_exchange uint8 = 16 23 | HandshakeType_client_certificate_request uint8 = 17 24 | HandshakeType_finished uint8 = 20 25 | HandshakeType_certificate_url uint8 = 21 26 | HandshakeType_certificate_status uint8 = 22 27 | HandshakeType_supplemental_data uint8 = 23 28 | HandshakeType_key_update uint8 = 24 29 | HandshakeType_compressed_certificate uint8 = 25 30 | HandshakeType_ekt_key uint8 = 26 31 | HandshakeType_message_hash uint8 = 254 32 | 33 | // Not IANA assigned 34 | HandshakeType_next_protocol uint8 = 67 35 | ) 36 | 37 | var DictHandshakeTypeValueIndexed = map[uint8]string{ 38 | 0: "hello_request", 39 | 1: "client_hello", 40 | 2: "server_hello", 41 | 3: "hello_verify_request", 42 | 4: "new_session_ticket", 43 | 5: "end_of_early_data", 44 | 6: "hello_retry_request", 45 | 7: "Unassigned", 46 | 8: "encrypted_extensions", 47 | 9: "request_connection_id", 48 | 10: "new_connection_id", 49 | 11: "certificate", 50 | 12: "server_key_exchange", 51 | 13: "certificate_request", 52 | 14: "server_hello_done", 53 | 15: "certificate_verify", 54 | 16: "client_key_exchange", 55 | 17: "client_certificate_request", 56 | 20: "finished", 57 | 21: "certificate_url", 58 | 22: "certificate_status", 59 | 23: "supplemental_data", 60 | 24: "key_update", 61 | 25: "compressed_certificate", 62 | 26: "ekt_key", 63 | 254: "message_hash", 64 | 65 | 67: "next_protocol", 66 | } 67 | 68 | var DictHandshakeTypeNameIndexed = map[string]uint8{ 69 | "hello_request": 0, 70 | "client_hello": 1, 71 | "server_hello": 2, 72 | "hello_verify_request": 3, 73 | "new_session_ticket": 4, 74 | "end_of_early_data": 5, 75 | "hello_retry_request": 6, 76 | "encrypted_extensions": 8, 77 | "request_connection_id": 9, 78 | "new_connection_id": 10, 79 | "certificate": 11, 80 | "server_key_exchange": 12, 81 | "certificate_request": 13, 82 | "server_hello_done": 14, 83 | "certificate_verify": 15, 84 | "client_key_exchange": 16, 85 | "client_certificate_request": 17, 86 | "finished": 20, 87 | "certificate_url": 21, 88 | "certificate_status": 22, 89 | "supplemental_data": 23, 90 | "key_update": 24, 91 | "compressed_certificate": 25, 92 | "ekt_key": 26, 93 | "message_hash": 254, 94 | 95 | "next_protocol": 67, 96 | } 97 | -------------------------------------------------------------------------------- /dicttls/hashalgorithm.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-18 4 | // last updated: March 2023 5 | 6 | const ( 7 | HashAlg_none uint8 = 0 // deprecated in TLS 1.3 8 | HashAlg_md5 uint8 = 1 // deprecated in TLS 1.3 9 | HashAlg_sha1 uint8 = 2 10 | HashAlg_sha224 uint8 = 3 // deprecated in TLS 1.3 11 | HashAlg_sha256 uint8 = 4 12 | HashAlg_sha384 uint8 = 5 13 | HashAlg_sha512 uint8 = 6 14 | HashAlg_Intrinsic uint8 = 8 15 | ) 16 | 17 | var DictHashAlgorithmValueIndexed = map[uint8]string{ 18 | 0: "none", 19 | 1: "md5", 20 | 2: "sha1", 21 | 3: "sha224", 22 | 4: "sha256", 23 | 5: "sha384", 24 | 6: "sha512", 25 | 7: "Reserved", 26 | 8: "Intrinsic", 27 | } 28 | 29 | var DictHashAlgorithmNameIndexed = map[string]uint8{ 30 | "none": 0, 31 | "md5": 1, 32 | "sha1": 2, 33 | "sha224": 3, 34 | "sha256": 4, 35 | "sha384": 5, 36 | "sha512": 6, 37 | "Reserved": 7, 38 | "Intrinsic": 8, 39 | } 40 | -------------------------------------------------------------------------------- /dicttls/heartbeat_message_types.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-parameters/heartbeat-message-types.csv 4 | // last updated: March 2023 5 | 6 | const ( 7 | HeartbeatMessage_request uint8 = 1 8 | HeartbeatMessage_response uint8 = 2 9 | ) 10 | 11 | var DictHeartbeatMessageTypeValueIndexed = map[uint8]string{ 12 | 1: "heartbeat_request", 13 | 2: "heartbeat_response", 14 | } 15 | 16 | var DictHeartbeatMessageTypeNameIndexed = map[string]uint8{ 17 | "heartbeat_request": 1, 18 | "heartbeat_response": 2, 19 | } 20 | -------------------------------------------------------------------------------- /dicttls/heartbeat_mode.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-parameters/heartbeat-modes.csv 4 | // last updated: March 2023 5 | 6 | const ( 7 | HeartbeatMode_peer_allowed_to_send uint8 = 1 8 | HeartbeatMode_peer_not_allowed_to_send uint8 = 2 9 | ) 10 | 11 | var DictHeartbeatModeValueIndexed = map[uint8]string{ 12 | 1: "peer_allowed_to_send", 13 | 2: "peer_not_allowed_to_send", 14 | } 15 | 16 | var DictHeartbeatModeNameIndexed = map[string]uint8{ 17 | "peer_allowed_to_send": 1, 18 | "peer_not_allowed_to_send": 2, 19 | } 20 | -------------------------------------------------------------------------------- /dicttls/hpke_aead_identifiers.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/hpke/hpke.xhtml 4 | // last updated: December 2023 5 | 6 | const ( 7 | AEAD_AES_128_GCM uint16 = 0x0001 // NIST Special Publication 800-38D 8 | AEAD_AES_256_GCM uint16 = 0x0002 // NIST Special Publication 800-38D 9 | AEAD_CHACHA20_POLY1305 uint16 = 0x0003 // RFC 8439 10 | AEAD_EXPORT_ONLY uint16 = 0xFFFF // RFC 9180 11 | ) 12 | 13 | var DictAEADIdentifierValueIndexed = map[uint16]string{ 14 | 0x0000: "Reserved", // RFC 9180 15 | 0x0001: "AES-128-GCM", 16 | 0x0002: "AES-256-GCM", 17 | 0x0003: "ChaCha20Poly1305", 18 | 0xFFFF: "Export-only", // RFC 9180 19 | } 20 | -------------------------------------------------------------------------------- /dicttls/hpke_kdf_identifiers.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/hpke/hpke.xhtml 4 | // last updated: December 2023 5 | 6 | const ( 7 | HKDF_SHA256 uint16 = 0x0001 8 | HKDF_SHA384 uint16 = 0x0002 9 | HKDF_SHA512 uint16 = 0x0003 10 | ) 11 | 12 | var DictKDFIdentifierValueIndexed = map[uint16]string{ 13 | 0x0000: "Reserved", // RFC 9180 14 | 0x0001: "HKDF_SHA256", 15 | 0x0002: "HKDF_SHA384", 16 | 0x0003: "HKDF_SHA512", 17 | } 18 | 19 | var DictKDFIdentifierNameIndexed = map[string]uint16{ 20 | "Reserved": 0x0000, // RFC 9180 21 | "HKDF_SHA256": 0x0001, 22 | "HKDF_SHA384": 0x0002, 23 | "HKDF_SHA512": 0x0003, 24 | } 25 | -------------------------------------------------------------------------------- /dicttls/hpke_kem_identifiers.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/hpke/hpke.xhtml 4 | // last updated: December 2023 5 | 6 | const ( 7 | DHKEM_P256_HKDF_SHA256 uint16 = 0x0010 // RFC 5869 8 | DHKEM_P384_HKDF_SHA384 uint16 = 0x0011 // RFC 5869 9 | DHKEM_P521_HKDF_SHA512 uint16 = 0x0012 // RFC 5869 10 | DHKEM_CP256_HKDF_SHA256 uint16 = 0x0013 // RFC 6090 11 | DHKEM_CP384_HKDF_SHA384 uint16 = 0x0014 // RFC 6090 12 | DHKEM_CP521_HKDF_SHA512 uint16 = 0x0015 // RFC 6090 13 | DHKEM_SECP256K1_HKDF_SHA256 uint16 = 0x0016 // draft-wahby-cfrg-hpke-kem-secp256k1-01 14 | 15 | DHKEM_X25519_HKDF_SHA256 uint16 = 0x0020 // RFC 7748 16 | DHKEM_X448_HKDF_SHA512 uint16 = 0x0021 // RFC 7748 17 | 18 | X25519_KYBER768_DRAFT00 uint16 = 0x0030 // draft-westerbaan-cfrg-hpke-xyber768d00-02 19 | ) 20 | 21 | var DictKEMIdentifierValueIndexed = map[uint16]string{ 22 | 0x0000: "Reserved", // RFC 9180 23 | 24 | 0x0010: "DHKEM(P-256, HKDF-SHA256)", 25 | 0x0011: "DHKEM(P-384, HKDF-SHA384)", 26 | 0x0012: "DHKEM(P-521, HKDF-SHA512)", 27 | 0x0013: "DHKEM(CP-256, HKDF-SHA256)", 28 | 0x0014: "DHKEM(CP-384, HKDF-SHA384)", 29 | 0x0015: "DHKEM(CP-521, HKDF-SHA512)", 30 | 0x0016: "DHKEM(secp256k1, HKDF-SHA256)", 31 | 32 | 0x0020: "DHKEM(X25519, HKDF-SHA256)", 33 | 0x0021: "DHKEM(X448, HKDF-SHA512)", 34 | 35 | 0x0030: "X25519Kyber768Draft00", 36 | } 37 | 38 | var DictKEMIdentifierNameIndexed = map[string]uint16{ 39 | "Reserved": 0x0000, // RFC 9180 40 | 41 | "DHKEM(P-256, HKDF-SHA256)": 0x0010, 42 | "DHKEM(P-384, HKDF-SHA384)": 0x0011, 43 | "DHKEM(P-521, HKDF-SHA512)": 0x0012, 44 | "DHKEM(CP-256, HKDF-SHA256)": 0x0013, 45 | "DHKEM(CP-384, HKDF-SHA384)": 0x0014, 46 | "DHKEM(CP-521, HKDF-SHA512)": 0x0015, 47 | "DHKEM(secp256k1, HKDF-SHA256)": 0x0016, 48 | 49 | "DHKEM(X25519, HKDF-SHA256)": 0x0020, 50 | "DHKEM(X448, HKDF-SHA512)": 0x0021, 51 | 52 | "X25519Kyber768Draft00": 0x0030, 53 | } 54 | -------------------------------------------------------------------------------- /dicttls/psk_key_exchange_mode.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-parameters/tls-pskkeyexchangemode.csv 4 | // last updated: March 2023 5 | 6 | const ( 7 | PSKKeyExchangeMode_psk_ke uint8 = 0 8 | PSKKeyExchangeMode_psk_dhe_ke uint8 = 1 9 | ) 10 | 11 | var DictPSKKeyExchangeModeValueIndexed = map[uint8]string{ 12 | 0: "psk_ke", 13 | 1: "psk_dhe_ke", 14 | } 15 | 16 | var DictPSKKeyExchangeModeNameIndexed = map[string]uint8{ 17 | "psk_ke": 0, 18 | "psk_dhe_ke": 1, 19 | } 20 | -------------------------------------------------------------------------------- /dicttls/quic_frame_types.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/quic/quic.xhtml#quic-frame-types 4 | // last updated: July 2023 5 | 6 | const ( 7 | QUICFrameType_PADDING uint8 = 0x00 8 | QUICFrameType_PING uint8 = 0x01 9 | QUICFrameType_ACK uint8 = 0x02 10 | QUICFrameType_ACK_ecn uint8 = 0x03 11 | QUICFrameType_RESET_STREAM uint8 = 0x04 12 | QUICFrameType_STOP_SENDING uint8 = 0x05 13 | QUICFrameType_CRYPTO uint8 = 0x06 14 | QUICFrameType_NEW_TOKEN uint8 = 0x07 15 | QUICFrameType_STREAM uint8 = 0x08 16 | QUICFrameType_STREAM_fin uint8 = 0x09 17 | QUICFrameType_STREAM_len uint8 = 0x0a 18 | QUICFrameType_STREAM_len_fin uint8 = 0x0b 19 | QUICFrameType_STREAM_off uint8 = 0x0c 20 | QUICFrameType_STREAM_off_fin uint8 = 0x0d 21 | QUICFrameType_STREAM_off_len uint8 = 0x0e 22 | QUICFrameType_STREAM_off_len_fin uint8 = 0x0f 23 | QUICFrameType_MAX_DATA uint8 = 0x10 24 | QUICFrameType_MAX_STREAM_DATA uint8 = 0x11 25 | QUICFrameType_MAX_STREAMS_bidi uint8 = 0x12 26 | QUICFrameType_MAX_STREAMS_uni uint8 = 0x13 27 | QUICFrameType_DATA_BLOCKED uint8 = 0x14 28 | QUICFrameType_STREAM_DATA_BLOCKED uint8 = 0x15 29 | QUICFrameType_STREAMS_BLOCKED_bidi uint8 = 0x16 30 | QUICFrameType_STREAMS_BLOCKED_uni uint8 = 0x17 31 | QUICFrameType_NEW_CONNECTION_ID uint8 = 0x18 32 | QUICFrameType_RETIRE_CONNECTION_ID uint8 = 0x19 33 | QUICFrameType_PATH_CHALLENGE uint8 = 0x1a 34 | QUICFrameType_PATH_RESPONSE uint8 = 0x1b 35 | QUICFrameType_CONNECTION_CLOSE uint8 = 0x1c 36 | QUICFrameType_CONNECTION_CLOSE_app uint8 = 0x1d 37 | QUICFrameType_HANDSHAKE_DONE uint8 = 0x1e 38 | QUICFrameType_DATAGRAM uint8 = 0x30 // RFC9221 39 | QUICFrameType_DATAGRAM_len uint8 = 0x31 // RFC9221 40 | ) 41 | 42 | var DictQUICFrameTypeValueIndexed = map[uint8]string{ 43 | 0x00: "PADDING", 44 | 0x01: "PING", 45 | 0x02: "ACK", 46 | 0x03: "ACK_ecn", 47 | 0x04: "RESET_STREAM", 48 | 0x05: "STOP_SENDING", 49 | 0x06: "CRYPTO", 50 | 0x07: "NEW_TOKEN", 51 | 0x08: "STREAM", 52 | 0x09: "STREAM_fin", 53 | 0x0a: "STREAM_len", 54 | 0x0b: "STREAM_len_fin", 55 | 0x0c: "STREAM_off", 56 | 0x0d: "STREAM_off_fin", 57 | 0x0e: "STREAM_off_len", 58 | 0x0f: "STREAM_off_len_fin", 59 | 0x10: "MAX_DATA", 60 | 0x11: "MAX_STREAM_DATA", 61 | 0x12: "MAX_STREAMS_bidi", 62 | 0x13: "MAX_STREAMS_uni", 63 | 0x14: "DATA_BLOCKED", 64 | 0x15: "STREAM_DATA_BLOCKED", 65 | 0x16: "STREAMS_BLOCKED_bidi", 66 | 0x17: "STREAMS_BLOCKED_uni", 67 | 0x18: "NEW_CONNECTION_ID", 68 | 0x19: "RETIRE_CONNECTION_ID", 69 | 0x1a: "PATH_CHALLENGE", 70 | 0x1b: "PATH_RESPONSE", 71 | 0x1c: "CONNECTION_CLOSE", 72 | 0x1d: "CONNECTION_CLOSE_app", 73 | 0x1e: "HANDSHAKE_DONE", 74 | 0x30: "DATAGRAM", 75 | 0x31: "DATAGRAM_len", 76 | } 77 | 78 | var DictQUICFrameTypeNameIndexed = map[string]uint8{ 79 | "PADDING": 0x00, 80 | "PING": 0x01, 81 | "ACK": 0x02, 82 | "ACK_ecn": 0x03, 83 | "RESET_STREAM": 0x04, 84 | "STOP_SENDING": 0x05, 85 | "CRYPTO": 0x06, 86 | "NEW_TOKEN": 0x07, 87 | "STREAM": 0x08, 88 | "STREAM_fin": 0x09, 89 | "STREAM_len": 0x0a, 90 | "STREAM_len_fin": 0x0b, 91 | "STREAM_off": 0x0c, 92 | "STREAM_off_fin": 0x0d, 93 | "STREAM_off_len": 0x0e, 94 | "STREAM_off_len_fin": 0x0f, 95 | "MAX_DATA": 0x10, 96 | "MAX_STREAM_DATA": 0x11, 97 | "MAX_STREAMS_bidi": 0x12, 98 | "MAX_STREAMS_uni": 0x13, 99 | "DATA_BLOCKED": 0x14, 100 | "STREAM_DATA_BLOCKED": 0x15, 101 | "STREAMS_BLOCKED_bidi": 0x16, 102 | "STREAMS_BLOCKED_uni": 0x17, 103 | "NEW_CONNECTION_ID": 0x18, 104 | "RETIRE_CONNECTION_ID": 0x19, 105 | "PATH_CHALLENGE": 0x1a, 106 | "PATH_RESPONSE": 0x1b, 107 | "CONNECTION_CLOSE": 0x1c, 108 | "CONNECTION_CLOSE_app": 0x1d, 109 | "HANDSHAKE_DONE": 0x1e, 110 | "DATAGRAM": 0x30, 111 | "DATAGRAM_len": 0x31, 112 | } 113 | -------------------------------------------------------------------------------- /dicttls/quic_transport_error_codes.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/quic/quic.xhtml#quic-transport-error-codes 4 | // last updated: July 2023 5 | 6 | const ( 7 | QUICTransportErrorCode_NO_ERROR uint16 = 0x0000 8 | QUICTransportErrorCode_INTERNAL_ERROR uint16 = 0x0001 9 | QUICTransportErrorCode_CONNECTION_REFUSED uint16 = 0x0002 10 | QUICTransportErrorCode_FLOW_CONTROL_ERROR uint16 = 0x0003 11 | QUICTransportErrorCode_STREAM_LIMIT_ERROR uint16 = 0x0004 12 | QUICTransportErrorCode_STREAM_STATE_ERROR uint16 = 0x0005 13 | QUICTransportErrorCode_FINAL_SIZE_ERROR uint16 = 0x0006 14 | QUICTransportErrorCode_FRAME_ENCODING_ERROR uint16 = 0x0007 15 | QUICTransportErrorCode_TRANSPORT_PARAMETER_ERROR uint16 = 0x0008 16 | QUICTransportErrorCode_CONNECTION_ID_LIMIT_ERROR uint16 = 0x0009 17 | QUICTransportErrorCode_PROTOCOL_VIOLATION uint16 = 0x000A 18 | QUICTransportErrorCode_INVALID_TOKEN uint16 = 0x000B 19 | QUICTransportErrorCode_APPLICATION_ERROR uint16 = 0x000C 20 | QUICTransportErrorCode_CRYPTO_BUFFER_EXCEEDED uint16 = 0x000D 21 | QUICTransportErrorCode_KEY_UPDATE_ERROR uint16 = 0x000E 22 | QUICTransportErrorCode_AEAD_LIMIT_REACHED uint16 = 0x000F 23 | QUICTransportErrorCode_NO_VIABLE_PATH uint16 = 0x0010 24 | QUICTransportErrorCode_VERSION_NEGOTIATION_ERROR uint16 = 0x0011 // RFC9368 25 | QUICTransportErrorCode_CRYPTO_ERROR uint16 = 0x0100 // 0x0100-0x01FF, use with bitwise operator 26 | ) 27 | 28 | var DictQUICTransportErrorCodeValueIndexed = map[uint16]string{ 29 | 0x0000: "NO_ERROR", 30 | 0x0001: "INTERNAL_ERROR", 31 | 0x0002: "CONNECTION_REFUSED", 32 | 0x0003: "FLOW_CONTROL_ERROR", 33 | 0x0004: "STREAM_LIMIT_ERROR", 34 | 0x0005: "STREAM_STATE_ERROR", 35 | 0x0006: "FINAL_SIZE_ERROR", 36 | 0x0007: "FRAME_ENCODING_ERROR", 37 | 0x0008: "TRANSPORT_PARAMETER_ERROR", 38 | 0x0009: "CONNECTION_ID_LIMIT_ERROR", 39 | 0x000A: "PROTOCOL_VIOLATION", 40 | 0x000B: "INVALID_TOKEN", 41 | 0x000C: "APPLICATION_ERROR", 42 | 0x000D: "CRYPTO_BUFFER_EXCEEDED", 43 | 0x000E: "KEY_UPDATE_ERROR", 44 | 0x000F: "AEAD_LIMIT_REACHED", 45 | 0x0010: "NO_VIABLE_PATH", 46 | 0x0011: "VERSION_NEGOTIATION_ERROR", 47 | 0x0100: "CRYPTO_ERROR", 48 | } 49 | 50 | var DictQUICTransportErrorCodeNameIndexed = map[string]uint16{ 51 | "NO_ERROR": 0x0000, 52 | "INTERNAL_ERROR": 0x0001, 53 | "CONNECTION_REFUSED": 0x0002, 54 | "FLOW_CONTROL_ERROR": 0x0003, 55 | "STREAM_LIMIT_ERROR": 0x0004, 56 | "STREAM_STATE_ERROR": 0x0005, 57 | "FINAL_SIZE_ERROR": 0x0006, 58 | "FRAME_ENCODING_ERROR": 0x0007, 59 | "TRANSPORT_PARAMETER_ERROR": 0x0008, 60 | "CONNECTION_ID_LIMIT_ERROR": 0x0009, 61 | "PROTOCOL_VIOLATION": 0x000A, 62 | "INVALID_TOKEN": 0x000B, 63 | "APPLICATION_ERROR": 0x000C, 64 | "CRYPTO_BUFFER_EXCEEDED": 0x000D, 65 | "KEY_UPDATE_ERROR": 0x000E, 66 | "AEAD_LIMIT_REACHED": 0x000F, 67 | "NO_VIABLE_PATH": 0x0010, 68 | "VERSION_NEGOTIATION_ERROR": 0x0011, 69 | "CRYPTO_ERROR": 0x0100, 70 | } 71 | -------------------------------------------------------------------------------- /dicttls/quic_transport_parameters.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/quic/quic.xhtml#quic-transport 4 | // last updated: July 2023 5 | 6 | const ( 7 | QUICTransportParameter_original_destination_connection_id uint64 = 0x00 8 | QUICTransportParameter_max_idle_timeout uint64 = 0x01 9 | QUICTransportParameter_stateless_reset_token uint64 = 0x02 10 | QUICTransportParameter_max_udp_payload_size uint64 = 0x03 11 | QUICTransportParameter_initial_max_data uint64 = 0x04 12 | QUICTransportParameter_initial_max_stream_data_bidi_local uint64 = 0x05 13 | QUICTransportParameter_initial_max_stream_data_bidi_remote uint64 = 0x06 14 | QUICTransportParameter_initial_max_stream_data_uni uint64 = 0x07 15 | QUICTransportParameter_initial_max_streams_bidi uint64 = 0x08 16 | QUICTransportParameter_initial_max_streams_uni uint64 = 0x09 17 | QUICTransportParameter_ack_delay_exponent uint64 = 0x0a 18 | QUICTransportParameter_max_ack_delay uint64 = 0x0b 19 | QUICTransportParameter_disable_active_migration uint64 = 0x0c 20 | QUICTransportParameter_preferred_address uint64 = 0x0d 21 | QUICTransportParameter_active_connection_id_limit uint64 = 0x0e 22 | QUICTransportParameter_initial_source_connection_id uint64 = 0x0f 23 | QUICTransportParameter_retry_source_connection_id uint64 = 0x10 24 | QUICTransportParameter_version_information uint64 = 0x11 // RFC9368 25 | QUICTransportParameter_max_datagram_frame_size uint64 = 0x20 // RFC9221 26 | QUICTransportParameter_discard uint64 = 0x173e // David_Schinazi: Receiver silently discards. https://github.com/quicwg/base-drafts/wiki/Quantum-Readiness-test 27 | QUICTransportParameter_google_handshake_message uint64 = 0x26ab // Google: Used to carry Google internal handshake message 28 | QUICTransportParameter_grease_quic_bit uint64 = 0x2ab2 // RFC9287 29 | QUICTransportParameter_initial_rtt uint64 = 0x3127 // Google: Initial RTT in microseconds 30 | QUICTransportParameter_google_connection_options uint64 = 0x3128 // Google: Google connection options for experimentation 31 | QUICTransportParameter_user_agent uint64 = 0x3129 // Google: User agent string (deprecated) 32 | QUICTransportParameter_google_version uint64 = 0x4752 // Google: Google QUIC version downgrade prevention 33 | ) 34 | 35 | var DictQUICTransportParameterValueIndexed = map[uint64]string{ 36 | 0x00: "original_destination_connection_id", 37 | 0x01: "max_idle_timeout", 38 | 0x02: "stateless_reset_token", 39 | 0x03: "max_udp_payload_size", 40 | 0x04: "initial_max_data", 41 | 0x05: "initial_max_stream_data_bidi_local", 42 | 0x06: "initial_max_stream_data_bidi_remote", 43 | 0x07: "initial_max_stream_data_uni", 44 | 0x08: "initial_max_streams_bidi", 45 | 0x09: "initial_max_streams_uni", 46 | 0x0a: "ack_delay_exponent", 47 | 0x0b: "max_ack_delay", 48 | 0x0c: "disable_active_migration", 49 | 0x0d: "preferred_address", 50 | 0x0e: "active_connection_id_limit", 51 | 0x0f: "initial_source_connection_id", 52 | 0x10: "retry_source_connection_id", 53 | 0x11: "version_information", 54 | 0x20: "max_datagram_frame_size", 55 | 0x173e: "discard", 56 | 0x26ab: "google handshake message", 57 | 0x2ab2: "grease_quic_bit", 58 | 0x3127: "initial_rtt", 59 | 0x3128: "google_connection_options", 60 | 0x3129: "user_agent", 61 | 0x4752: "google_version", 62 | } 63 | 64 | var DictQUICTransportParameterNameIndexed = map[string]uint64{ 65 | "original_destination_connection_id": 0x00, 66 | "max_idle_timeout": 0x01, 67 | "stateless_reset_token": 0x02, 68 | "max_udp_payload_size": 0x03, 69 | "initial_max_data": 0x04, 70 | "initial_max_stream_data_bidi_local": 0x05, 71 | "initial_max_stream_data_bidi_remote": 0x06, 72 | "initial_max_stream_data_uni": 0x07, 73 | "initial_max_streams_bidi": 0x08, 74 | "initial_max_streams_uni": 0x09, 75 | "ack_delay_exponent": 0x0a, 76 | "max_ack_delay": 0x0b, 77 | "disable_active_migration": 0x0c, 78 | "preferred_address": 0x0d, 79 | "active_connection_id_limit": 0x0e, 80 | "initial_source_connection_id": 0x0f, 81 | "retry_source_connection_id": 0x10, 82 | "version_information": 0x11, 83 | "max_datagram_frame_size": 0x20, 84 | "discard": 0x173e, 85 | "google handshake message": 0x26ab, 86 | "grease_quic_bit": 0x2ab2, 87 | "initial_rtt": 0x3127, 88 | "google_connection_options": 0x3128, 89 | "user_agent": 0x3129, 90 | "google_version": 0x4752, 91 | } 92 | -------------------------------------------------------------------------------- /dicttls/signaturealgorithm.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // Note: values in this file was used in TLS 1.2's signature_algorithms extension 4 | // in combination with the values in hashalgorithm.go. 5 | // signature_algorithms extension in TLS 1.3 uses values in signaturescheme.go 6 | 7 | // source: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-16 8 | // last updated: March 2023 9 | 10 | const ( 11 | SigAlg_anonymous uint8 = 0 // deprecated in TLS 1.3 12 | SigAlg_rsa uint8 = 1 13 | SigAlg_dsa uint8 = 2 // deprecated in TLS 1.3 14 | SigAlg_ecdsa uint8 = 3 15 | SigAlg_ed25519 uint8 = 7 16 | SigAlg_ed448 uint8 = 8 17 | SigAlg_gostr34102012_256 uint8 = 64 // value changed in TLS 1.3, to 0x0709-0x070C 18 | SigAlg_gostr34102012_512 uint8 = 65 // value changed in TLS 1.3, to 0x070D-0x070F 19 | ) 20 | 21 | var DictSignatureAlgorithmValueIndexed = map[uint8]string{ 22 | 0: "anonymous", 23 | 1: "rsa", 24 | 2: "dsa", 25 | 3: "ecdsa", 26 | 7: "ed25519", 27 | 8: "ed448", 28 | 64: "gostr34102012_256", 29 | 65: "gostr34102012_512", 30 | } 31 | 32 | var DictSignatureAlgorithmNameIndexed = map[string]uint8{ 33 | "anonymous": 0, 34 | "rsa": 1, 35 | "dsa": 2, 36 | "ecdsa": 3, 37 | "ed25519": 7, 38 | "ed448": 8, 39 | "gostr34102012_256": 64, 40 | "gostr34102012_512": 65, 41 | } 42 | -------------------------------------------------------------------------------- /dicttls/signaturescheme.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-parameters/tls-signaturescheme.csv 4 | // last updated: March 2023 5 | 6 | const ( 7 | SigScheme_rsa_pkcs1_sha1 uint16 = 0x0201 8 | SigScheme_ecdsa_sha1 uint16 = 0x0203 9 | SigScheme_rsa_pkcs1_sha256 uint16 = 0x0401 10 | SigScheme_ecdsa_secp256r1_sha256 uint16 = 0x0403 11 | SigScheme_rsa_pkcs1_sha256_legacy uint16 = 0x0420 12 | SigScheme_rsa_pkcs1_sha384 uint16 = 0x0501 13 | SigScheme_ecdsa_secp384r1_sha384 uint16 = 0x0503 14 | SigScheme_rsa_pkcs1_sha384_legacy uint16 = 0x0520 15 | SigScheme_rsa_pkcs1_sha512 uint16 = 0x0601 16 | SigScheme_ecdsa_secp521r1_sha512 uint16 = 0x0603 17 | SigScheme_rsa_pkcs1_sha512_legacy uint16 = 0x0620 18 | SigScheme_eccsi_sha256 uint16 = 0x0704 19 | SigScheme_iso_ibs1 uint16 = 0x0705 20 | SigScheme_iso_ibs2 uint16 = 0x0706 21 | SigScheme_iso_chinese_ibs uint16 = 0x0707 22 | SigScheme_sm2sig_sm3 uint16 = 0x0708 23 | SigScheme_gostr34102012_256a uint16 = 0x0709 24 | SigScheme_gostr34102012_256b uint16 = 0x070A 25 | SigScheme_gostr34102012_256c uint16 = 0x070B 26 | SigScheme_gostr34102012_256d uint16 = 0x070C 27 | SigScheme_gostr34102012_512a uint16 = 0x070D 28 | SigScheme_gostr34102012_512b uint16 = 0x070E 29 | SigScheme_gostr34102012_512c uint16 = 0x070F 30 | SigScheme_rsa_pss_rsae_sha256 uint16 = 0x0804 31 | SigScheme_rsa_pss_rsae_sha384 uint16 = 0x0805 32 | SigScheme_rsa_pss_rsae_sha512 uint16 = 0x0806 33 | SigScheme_ed25519 uint16 = 0x0807 34 | SigScheme_ed448 uint16 = 0x0808 35 | SigScheme_rsa_pss_pss_sha256 uint16 = 0x0809 36 | SigScheme_rsa_pss_pss_sha384 uint16 = 0x080A 37 | SigScheme_rsa_pss_pss_sha512 uint16 = 0x080B 38 | SigScheme_ecdsa_brainpoolP256r1tls13_sha256 uint16 = 0x081A 39 | SigScheme_ecdsa_brainpoolP384r1tls13_sha384 uint16 = 0x081B 40 | SigScheme_ecdsa_brainpoolP512r1tls13_sha512 uint16 = 0x081C 41 | ) 42 | 43 | var DictSignatureSchemeValueIndexed = map[uint16]string{ 44 | 0x0201: "rsa_pkcs1_sha1", 45 | 0x0203: "ecdsa_sha1", 46 | 0x0401: "rsa_pkcs1_sha256", 47 | 0x0403: "ecdsa_secp256r1_sha256", 48 | 0x0420: "rsa_pkcs1_sha256_legacy", 49 | 0x0501: "rsa_pkcs1_sha384", 50 | 0x0503: "ecdsa_secp384r1_sha384", 51 | 0x0520: "rsa_pkcs1_sha384_legacy", 52 | 0x0601: "rsa_pkcs1_sha512", 53 | 0x0603: "ecdsa_secp521r1_sha512", 54 | 0x0620: "rsa_pkcs1_sha512_legacy", 55 | 0x0704: "eccsi_sha256", 56 | 0x0705: "iso_ibs1", 57 | 0x0706: "iso_ibs2", 58 | 0x0707: "iso_chinese_ibs", 59 | 0x0708: "sm2sig_sm3", 60 | 0x0709: "gostr34102012_256a", 61 | 0x070A: "gostr34102012_256b", 62 | 0x070B: "gostr34102012_256c", 63 | 0x070C: "gostr34102012_256d", 64 | 0x070D: "gostr34102012_512a", 65 | 0x070E: "gostr34102012_512b", 66 | 0x070F: "gostr34102012_512c", 67 | 0x0804: "rsa_pss_rsae_sha256", 68 | 0x0805: "rsa_pss_rsae_sha384", 69 | 0x0806: "rsa_pss_rsae_sha512", 70 | 0x0807: "ed25519", 71 | 0x0808: "ed448", 72 | 0x0809: "rsa_pss_pss_sha256", 73 | 0x080A: "rsa_pss_pss_sha384", 74 | 0x080B: "rsa_pss_pss_sha512", 75 | 0x081A: "ecdsa_brainpoolP256r1tls13_sha256", 76 | 0x081B: "ecdsa_brainpoolP384r1tls13_sha384", 77 | 0x081C: "ecdsa_brainpoolP512r1tls13_sha512", 78 | } 79 | 80 | var DictSignatureSchemeNameIndexed = map[string]uint16{ 81 | "rsa_pkcs1_sha1": 0x0201, 82 | "Reserved for backward compatibility": 0x0202, 83 | "ecdsa_sha1": 0x0203, 84 | "rsa_pkcs1_sha256": 0x0401, 85 | "ecdsa_secp256r1_sha256": 0x0403, 86 | "rsa_pkcs1_sha256_legacy": 0x0420, 87 | "rsa_pkcs1_sha384": 0x0501, 88 | "ecdsa_secp384r1_sha384": 0x0503, 89 | "rsa_pkcs1_sha384_legacy": 0x0520, 90 | "rsa_pkcs1_sha512": 0x0601, 91 | "ecdsa_secp521r1_sha512": 0x0603, 92 | "rsa_pkcs1_sha512_legacy": 0x0620, 93 | "eccsi_sha256": 0x0704, 94 | "iso_ibs1": 0x0705, 95 | "iso_ibs2": 0x0706, 96 | "iso_chinese_ibs": 0x0707, 97 | "sm2sig_sm3": 0x0708, 98 | "gostr34102012_256a": 0x0709, 99 | "gostr34102012_256b": 0x070A, 100 | "gostr34102012_256c": 0x070B, 101 | "gostr34102012_256d": 0x070C, 102 | "gostr34102012_512a": 0x070D, 103 | "gostr34102012_512b": 0x070E, 104 | "gostr34102012_512c": 0x070F, 105 | "rsa_pss_rsae_sha256": 0x0804, 106 | "rsa_pss_rsae_sha384": 0x0805, 107 | "rsa_pss_rsae_sha512": 0x0806, 108 | "ed25519": 0x0807, 109 | "ed448": 0x0808, 110 | "rsa_pss_pss_sha256": 0x0809, 111 | "rsa_pss_pss_sha384": 0x080A, 112 | "rsa_pss_pss_sha512": 0x080B, 113 | "ecdsa_brainpoolP256r1tls13_sha256": 0x081A, 114 | "ecdsa_brainpoolP384r1tls13_sha384": 0x081B, 115 | "ecdsa_brainpoolP512r1tls13_sha512": 0x081C, 116 | } 117 | -------------------------------------------------------------------------------- /dicttls/supplemental_data_formats.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-12 4 | // last updated: March 2023 5 | 6 | const ( 7 | SupplementalDataType_user_mapping_data uint16 = 0 8 | SupplementalDataType_authz_data uint16 = 16386 9 | ) 10 | 11 | var DictSupplementalDataFormatValueIndexed = map[uint16]string{ 12 | 0: "user_mapping_data", 13 | 16386: "authz_data", 14 | } 15 | 16 | var DictSupplementalDataFormatNameIndexed = map[string]uint16{ 17 | "user_mapping_data": 0, 18 | "authz_data": 16386, 19 | } 20 | -------------------------------------------------------------------------------- /dicttls/usermappingtype_values.go: -------------------------------------------------------------------------------- 1 | package dicttls 2 | 3 | // source: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-14 4 | // last updated: March 2023 5 | 6 | const ( 7 | UserMappingType_upn_domain_hint uint8 = 64 8 | ) 9 | 10 | var DictUserMappingTypeValueIndexed = map[uint8]string{ 11 | 64: "upn_domain_hint", 12 | } 13 | 14 | var DictUserMappingTypeNameIndexed = map[string]uint8{ 15 | "upn_domain_hint": 64, 16 | } 17 | -------------------------------------------------------------------------------- /ech_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. 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 | "encoding/hex" 9 | "testing" 10 | ) 11 | 12 | func TestDecodeECHConfigLists(t *testing.T) { 13 | for _, tc := range []struct { 14 | list string 15 | numConfigs int 16 | }{ 17 | {"0045fe0d0041590020002092a01233db2218518ccbbbbc24df20686af417b37388de6460e94011974777090004000100010012636c6f7564666c6172652d6563682e636f6d0000", 1}, 18 | {"0105badd00050504030201fe0d0066000010004104e62b69e2bf659f97be2f1e0d948a4cd5976bb7a91e0d46fbdda9a91e9ddcba5a01e7d697a80a18f9c3c4a31e56e27c8348db161a1cf51d7ef1942d4bcf7222c1000c000100010001000200010003400e7075626c69632e6578616d706c650000fe0d003d00002000207d661615730214aeee70533366f36a609ead65c0c208e62322346ab5bcd8de1c000411112222400e7075626c69632e6578616d706c650000fe0d004d000020002085bd6a03277c25427b52e269e0c77a8eb524ba1eb3d2f132662d4b0ac6cb7357000c000100010001000200010003400e7075626c69632e6578616d706c650008aaaa000474657374", 3}, 19 | } { 20 | b, err := hex.DecodeString(tc.list) 21 | if err != nil { 22 | t.Fatal(err) 23 | } 24 | configs, err := parseECHConfigList(b) 25 | if err != nil { 26 | t.Fatal(err) 27 | } 28 | if len(configs) != tc.numConfigs { 29 | t.Fatalf("unexpected number of configs parsed: got %d want %d", len(configs), tc.numConfigs) 30 | } 31 | } 32 | 33 | } 34 | 35 | func TestSkipBadConfigs(t *testing.T) { 36 | b, err := hex.DecodeString("00c8badd00050504030201fe0d0029006666000401020304000c000100010001000200010003400e7075626c69632e6578616d706c650000fe0d003d000020002072e8a23b7aef67832bcc89d652e3870a60f88ca684ec65d6eace6b61f136064c000411112222400e7075626c69632e6578616d706c650000fe0d004d00002000200ce95810a81d8023f41e83679bc92701b2acd46c75869f95c72bc61c6b12297c000c000100010001000200010003400e7075626c69632e6578616d706c650008aaaa000474657374") 37 | if err != nil { 38 | t.Fatal(err) 39 | } 40 | configs, err := parseECHConfigList(b) 41 | if err != nil { 42 | t.Fatal(err) 43 | } 44 | config := pickECHConfig(configs) 45 | if config != nil { 46 | t.Fatal("pickECHConfig picked an invalid config") 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /examples/ech/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | // "crypto/tls" 6 | "encoding/base64" 7 | 8 | "errors" 9 | "fmt" 10 | "io" 11 | "log" 12 | "net" 13 | "net/http" 14 | "net/url" 15 | "os" 16 | "time" 17 | 18 | tls "github.com/refraction-networking/utls" 19 | "golang.org/x/net/http2" 20 | ) 21 | 22 | var ( 23 | dialTimeout = time.Duration(15) * time.Second 24 | ) 25 | 26 | // var requestHostname = "crypto.cloudflare.com" // speaks http2 and TLS 1.3 and ECH and PQ 27 | // var requestAddr = "crypto.cloudflare.com:443" 28 | // var requestPath = "/cdn-cgi/trace" 29 | 30 | var requestHostname = "tls-ech.dev" // speaks http2 and TLS 1.3 and ECH and PQ 31 | var requestAddr = "tls-ech.dev:443" 32 | var requestPath = "/" 33 | 34 | // var requestHostname = "defo.ie" // speaks http2 and TLS 1.3 and ECH and PQ 35 | // var requestAddr = "defo.ie:443" 36 | // var requestPath = "/ech-check.php" 37 | 38 | // var requestHostname = "client.tlsfingerprint.io" // speaks http2 and TLS 1.3 and ECH and PQ 39 | // var requestAddr = "client.tlsfingerprint.io:443" 40 | // var requestPath = "/" 41 | 42 | func HttpGetCustom(hostname string, addr string) (*http.Response, error) { 43 | klw, err := os.OpenFile("./sslkeylogging.log", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 44 | if err != nil { 45 | return nil, fmt.Errorf("os.OpenFile error: %+v", err) 46 | } 47 | 48 | echConf, err := base64.RawStdEncoding.DecodeString("AEn+DQBFKwAgACABWIHUGj4u+PIggYXcR5JF0gYk3dCRioBW8uJq9H4mKAAIAAEAAQABAANAEnB1YmxpYy50bHMtZWNoLmRldgAA") 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | config := tls.Config{ 54 | ServerName: hostname, 55 | KeyLogWriter: klw, 56 | EncryptedClientHelloConfigList: echConf, 57 | } 58 | dialConn, err := net.DialTimeout("tcp", addr, dialTimeout) 59 | if err != nil { 60 | return nil, fmt.Errorf("net.DialTimeout error: %+v", err) 61 | } 62 | uTlsConn := tls.UClient(dialConn, &config, tls.HelloGolang) 63 | // uTlsConn := tls.Client(dialConn, &config) 64 | defer uTlsConn.Close() 65 | 66 | // do not use this particular spec in production 67 | // make sure to generate a separate copy of ClientHelloSpec for every connection 68 | // spec, err := tls.UTLSIdToSpec(tls.HelloChrome_120) 69 | // // spec, err := tls.UTLSIdToSpec(tls.HelloFirefox_120) 70 | // if err != nil { 71 | // return nil, fmt.Errorf("tls.UTLSIdToSpec error: %+v", err) 72 | // } 73 | 74 | // err = uTlsConn.ApplyPreset(&spec) 75 | // if err != nil { 76 | // return nil, fmt.Errorf("uTlsConn.Handshake() error: %+v", err) 77 | // } 78 | 79 | err = uTlsConn.Handshake() 80 | if err != nil { 81 | return nil, fmt.Errorf("uTlsConn.Handshake() error: %+v", err) 82 | } 83 | 84 | return httpGetOverConn(uTlsConn, uTlsConn.ConnectionState().NegotiatedProtocol) 85 | } 86 | 87 | func httpGetOverConn(conn net.Conn, alpn string) (*http.Response, error) { 88 | req := &http.Request{ 89 | Method: "GET", 90 | URL: &url.URL{Scheme: "https", Host: requestHostname, Path: requestPath}, 91 | Header: make(http.Header), 92 | Host: requestHostname, 93 | } 94 | 95 | switch alpn { 96 | case "h2": 97 | log.Println("HTTP/2 enabled") 98 | req.Proto = "HTTP/2.0" 99 | req.ProtoMajor = 2 100 | req.ProtoMinor = 0 101 | 102 | tr := http2.Transport{} 103 | cConn, err := tr.NewClientConn(conn) 104 | if err != nil { 105 | return nil, err 106 | } 107 | return cConn.RoundTrip(req) 108 | case "http/1.1", "": 109 | log.Println("Using HTTP/1.1") 110 | req.Proto = "HTTP/1.1" 111 | req.ProtoMajor = 1 112 | req.ProtoMinor = 1 113 | 114 | err := req.Write(conn) 115 | if err != nil { 116 | return nil, err 117 | } 118 | return http.ReadResponse(bufio.NewReader(conn), req) 119 | default: 120 | return nil, fmt.Errorf("unsupported ALPN: %v", alpn) 121 | } 122 | } 123 | 124 | func main() { 125 | resp, err := HttpGetCustom(requestHostname, requestAddr) 126 | if err != nil { 127 | panic(err) 128 | } 129 | fmt.Printf("Response: %+v\n", resp) 130 | // read from resp.Body 131 | body := make([]byte, 65535) 132 | n, err := resp.Body.Read(body) 133 | if err != nil && !errors.Is(err, io.EOF) { 134 | panic(err) 135 | } 136 | 137 | fmt.Printf("Body: %s\n", body[:n]) 138 | } 139 | -------------------------------------------------------------------------------- /fipsonly/fipsonly.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. 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 | //go:build boringcrypto 6 | 7 | // Package fipsonly restricts all TLS configuration to FIPS-approved settings. 8 | // 9 | // The effect is triggered by importing the package anywhere in a program, as in: 10 | // 11 | // import _ "crypto/tls/fipsonly" 12 | // 13 | // This package only exists when using Go compiled with GOEXPERIMENT=boringcrypto. 14 | package fipsonly 15 | 16 | // This functionality is provided as a side effect of an import to make 17 | // it trivial to add to an existing program. It requires only a single line 18 | // added to an existing source file, or it can be done by adding a whole 19 | // new source file and not modifying any existing source files. 20 | 21 | import ( 22 | "crypto/internal/boring/sig" 23 | "crypto/tls/internal/fips140tls" 24 | ) 25 | 26 | func init() { 27 | fips140tls.Force() 28 | sig.FIPSOnly() 29 | } 30 | -------------------------------------------------------------------------------- /fipsonly/fipsonly_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. 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 | //go:build boringcrypto 6 | 7 | package fipsonly 8 | 9 | import ( 10 | "crypto/tls/internal/fips140tls" 11 | "testing" 12 | ) 13 | 14 | func Test(t *testing.T) { 15 | if !fips140tls.Required() { 16 | t.Fatal("fips140tls.Required() = false, must be true") 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/refraction-networking/utls 2 | 3 | go 1.24 4 | 5 | retract ( 6 | v1.4.1 // #218 7 | v1.4.0 // #218 panic on saveSessionTicket 8 | ) 9 | 10 | require ( 11 | github.com/andybalholm/brotli v1.0.6 12 | github.com/cloudflare/circl v1.5.0 13 | github.com/klauspost/compress v1.17.4 14 | golang.org/x/crypto v0.36.0 15 | golang.org/x/net v0.38.0 16 | golang.org/x/sys v0.31.0 17 | ) 18 | 19 | require golang.org/x/text v0.23.0 // indirect 20 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= 2 | github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= 3 | github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys= 4 | github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= 5 | github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= 6 | github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= 7 | golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= 8 | golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= 9 | golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= 10 | golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= 11 | golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= 12 | golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 13 | golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= 14 | golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= 15 | -------------------------------------------------------------------------------- /handshake_unix_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. 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 | //go:build unix 6 | 7 | package tls 8 | 9 | import ( 10 | "errors" 11 | "syscall" 12 | ) 13 | 14 | func init() { 15 | isConnRefused = func(err error) bool { 16 | return errors.Is(err, syscall.ECONNREFUSED) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /internal/boring/notboring.go: -------------------------------------------------------------------------------- 1 | package boring 2 | 3 | import ( 4 | "crypto/cipher" 5 | "errors" 6 | ) 7 | 8 | const Enabled bool = false 9 | 10 | func NewGCMTLS(_ cipher.Block) (cipher.AEAD, error) { 11 | return nil, errors.New("boring not implemented") 12 | } 13 | 14 | func NewGCMTLS13(_ cipher.Block) (cipher.AEAD, error) { 15 | return nil, errors.New("boring not implemented") 16 | } 17 | 18 | func Unreachable() { 19 | // do nothing 20 | } 21 | -------------------------------------------------------------------------------- /internal/byteorder/byteorder.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. 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 byteorder provides functions for decoding and encoding 6 | // little and big endian integer types from/to byte slices. 7 | package byteorder 8 | 9 | func LEUint16(b []byte) uint16 { 10 | _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 11 | return uint16(b[0]) | uint16(b[1])<<8 12 | } 13 | 14 | func LEPutUint16(b []byte, v uint16) { 15 | _ = b[1] // early bounds check to guarantee safety of writes below 16 | b[0] = byte(v) 17 | b[1] = byte(v >> 8) 18 | } 19 | 20 | func LEAppendUint16(b []byte, v uint16) []byte { 21 | return append(b, 22 | byte(v), 23 | byte(v>>8), 24 | ) 25 | } 26 | 27 | func LEUint32(b []byte) uint32 { 28 | _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 29 | return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 30 | } 31 | 32 | func LEPutUint32(b []byte, v uint32) { 33 | _ = b[3] // early bounds check to guarantee safety of writes below 34 | b[0] = byte(v) 35 | b[1] = byte(v >> 8) 36 | b[2] = byte(v >> 16) 37 | b[3] = byte(v >> 24) 38 | } 39 | 40 | func LEAppendUint32(b []byte, v uint32) []byte { 41 | return append(b, 42 | byte(v), 43 | byte(v>>8), 44 | byte(v>>16), 45 | byte(v>>24), 46 | ) 47 | } 48 | 49 | func LEUint64(b []byte) uint64 { 50 | _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 51 | return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | 52 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 53 | } 54 | 55 | func LEPutUint64(b []byte, v uint64) { 56 | _ = b[7] // early bounds check to guarantee safety of writes below 57 | b[0] = byte(v) 58 | b[1] = byte(v >> 8) 59 | b[2] = byte(v >> 16) 60 | b[3] = byte(v >> 24) 61 | b[4] = byte(v >> 32) 62 | b[5] = byte(v >> 40) 63 | b[6] = byte(v >> 48) 64 | b[7] = byte(v >> 56) 65 | } 66 | 67 | func LEAppendUint64(b []byte, v uint64) []byte { 68 | return append(b, 69 | byte(v), 70 | byte(v>>8), 71 | byte(v>>16), 72 | byte(v>>24), 73 | byte(v>>32), 74 | byte(v>>40), 75 | byte(v>>48), 76 | byte(v>>56), 77 | ) 78 | } 79 | 80 | func BEUint16(b []byte) uint16 { 81 | _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 82 | return uint16(b[1]) | uint16(b[0])<<8 83 | } 84 | 85 | func BEPutUint16(b []byte, v uint16) { 86 | _ = b[1] // early bounds check to guarantee safety of writes below 87 | b[0] = byte(v >> 8) 88 | b[1] = byte(v) 89 | } 90 | 91 | func BEAppendUint16(b []byte, v uint16) []byte { 92 | return append(b, 93 | byte(v>>8), 94 | byte(v), 95 | ) 96 | } 97 | 98 | func BEUint32(b []byte) uint32 { 99 | _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 100 | return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 101 | } 102 | 103 | func BEPutUint32(b []byte, v uint32) { 104 | _ = b[3] // early bounds check to guarantee safety of writes below 105 | b[0] = byte(v >> 24) 106 | b[1] = byte(v >> 16) 107 | b[2] = byte(v >> 8) 108 | b[3] = byte(v) 109 | } 110 | 111 | func BEAppendUint32(b []byte, v uint32) []byte { 112 | return append(b, 113 | byte(v>>24), 114 | byte(v>>16), 115 | byte(v>>8), 116 | byte(v), 117 | ) 118 | } 119 | 120 | func BEUint64(b []byte) uint64 { 121 | _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 122 | return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | 123 | uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 124 | } 125 | 126 | func BEPutUint64(b []byte, v uint64) { 127 | _ = b[7] // early bounds check to guarantee safety of writes below 128 | b[0] = byte(v >> 56) 129 | b[1] = byte(v >> 48) 130 | b[2] = byte(v >> 40) 131 | b[3] = byte(v >> 32) 132 | b[4] = byte(v >> 24) 133 | b[5] = byte(v >> 16) 134 | b[6] = byte(v >> 8) 135 | b[7] = byte(v) 136 | } 137 | 138 | func BEAppendUint64(b []byte, v uint64) []byte { 139 | return append(b, 140 | byte(v>>56), 141 | byte(v>>48), 142 | byte(v>>40), 143 | byte(v>>32), 144 | byte(v>>24), 145 | byte(v>>16), 146 | byte(v>>8), 147 | byte(v), 148 | ) 149 | } 150 | -------------------------------------------------------------------------------- /internal/fips140tls/fipstls.go: -------------------------------------------------------------------------------- 1 | package fips140tls 2 | 3 | func Required() bool { 4 | return false 5 | } 6 | -------------------------------------------------------------------------------- /internal/helper/typeconv.go: -------------------------------------------------------------------------------- 1 | package helper 2 | 3 | import ( 4 | "errors" 5 | 6 | "golang.org/x/crypto/cryptobyte" 7 | ) 8 | 9 | // Uint8to16 converts a slice of uint8 to a slice of uint16. 10 | // e.g. []uint8{0x00, 0x01, 0x00, 0x02} -> []uint16{0x0001, 0x0002} 11 | func Uint8to16(in []uint8) ([]uint16, error) { 12 | s := cryptobyte.String(in) 13 | var out []uint16 14 | for !s.Empty() { 15 | var v uint16 16 | if s.ReadUint16(&v) { 17 | out = append(out, v) 18 | } else { 19 | return nil, errors.New("ReadUint16 failed") 20 | } 21 | } 22 | return out, nil 23 | } 24 | -------------------------------------------------------------------------------- /internal/hkdf/hkdf.go: -------------------------------------------------------------------------------- 1 | package hkdf 2 | 3 | import ( 4 | "crypto/hkdf" 5 | "hash" 6 | ) 7 | 8 | func Extract[H hash.Hash](h func() H, secret, salt []byte) []byte { 9 | res, err := hkdf.Extract(h, secret, salt) 10 | if err != nil { 11 | panic(err) 12 | } 13 | 14 | return res 15 | } 16 | 17 | func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLength int) []byte { 18 | res, err := hkdf.Expand(h, pseudorandomKey, info, keyLength) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | return res 24 | } 25 | -------------------------------------------------------------------------------- /internal/quicvarint/protocol/protocol.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The quic-go Authors. All rights reserved. 2 | // Use of this source code is governed by a MIT-style 3 | // license that can be found in the LICENSE file of 4 | // the quic-go repository. 5 | 6 | package protocol 7 | 8 | import ( 9 | "fmt" 10 | "time" 11 | ) 12 | 13 | // The PacketType is the Long Header Type 14 | type PacketType uint8 15 | 16 | const ( 17 | // PacketTypeInitial is the packet type of an Initial packet 18 | PacketTypeInitial PacketType = 1 + iota 19 | // PacketTypeRetry is the packet type of a Retry packet 20 | PacketTypeRetry 21 | // PacketTypeHandshake is the packet type of a Handshake packet 22 | PacketTypeHandshake 23 | // PacketType0RTT is the packet type of a 0-RTT packet 24 | PacketType0RTT 25 | ) 26 | 27 | func (t PacketType) String() string { 28 | switch t { 29 | case PacketTypeInitial: 30 | return "Initial" 31 | case PacketTypeRetry: 32 | return "Retry" 33 | case PacketTypeHandshake: 34 | return "Handshake" 35 | case PacketType0RTT: 36 | return "0-RTT Protected" 37 | default: 38 | return fmt.Sprintf("unknown packet type: %d", t) 39 | } 40 | } 41 | 42 | type ECN uint8 43 | 44 | const ( 45 | ECNUnsupported ECN = iota 46 | ECNNon // 00 47 | ECT1 // 01 48 | ECT0 // 10 49 | ECNCE // 11 50 | ) 51 | 52 | func ParseECNHeaderBits(bits byte) ECN { 53 | switch bits { 54 | case 0: 55 | return ECNNon 56 | case 0b00000010: 57 | return ECT0 58 | case 0b00000001: 59 | return ECT1 60 | case 0b00000011: 61 | return ECNCE 62 | default: 63 | panic("invalid ECN bits") 64 | } 65 | } 66 | 67 | func (e ECN) ToHeaderBits() byte { 68 | //nolint:exhaustive // There are only 4 values. 69 | switch e { 70 | case ECNNon: 71 | return 0 72 | case ECT0: 73 | return 0b00000010 74 | case ECT1: 75 | return 0b00000001 76 | case ECNCE: 77 | return 0b00000011 78 | default: 79 | panic("ECN unsupported") 80 | } 81 | } 82 | 83 | func (e ECN) String() string { 84 | switch e { 85 | case ECNUnsupported: 86 | return "ECN unsupported" 87 | case ECNNon: 88 | return "Not-ECT" 89 | case ECT1: 90 | return "ECT(1)" 91 | case ECT0: 92 | return "ECT(0)" 93 | case ECNCE: 94 | return "CE" 95 | default: 96 | return fmt.Sprintf("invalid ECN value: %d", e) 97 | } 98 | } 99 | 100 | // A ByteCount in QUIC 101 | type ByteCount int64 102 | 103 | // MaxByteCount is the maximum value of a ByteCount 104 | const MaxByteCount = ByteCount(1<<62 - 1) 105 | 106 | // InvalidByteCount is an invalid byte count 107 | const InvalidByteCount ByteCount = -1 108 | 109 | // A StatelessResetToken is a stateless reset token. 110 | type StatelessResetToken [16]byte 111 | 112 | // MaxPacketBufferSize maximum packet size of any QUIC packet, based on 113 | // ethernet's max size, minus the IP and UDP headers. IPv6 has a 40 byte header, 114 | // UDP adds an additional 8 bytes. This is a total overhead of 48 bytes. 115 | // Ethernet's max packet size is 1500 bytes, 1500 - 48 = 1452. 116 | const MaxPacketBufferSize = 1452 117 | 118 | // MaxLargePacketBufferSize is used when using GSO 119 | const MaxLargePacketBufferSize = 20 * 1024 120 | 121 | // MinInitialPacketSize is the minimum size an Initial packet is required to have. 122 | const MinInitialPacketSize = 1200 123 | 124 | // MinUnknownVersionPacketSize is the minimum size a packet with an unknown version 125 | // needs to have in order to trigger a Version Negotiation packet. 126 | const MinUnknownVersionPacketSize = MinInitialPacketSize 127 | 128 | // MinStatelessResetSize is the minimum size of a stateless reset packet that we send 129 | const MinStatelessResetSize = 1 /* first byte */ + 20 /* max. conn ID length */ + 4 /* max. packet number length */ + 1 /* min. payload length */ + 16 /* token */ 130 | 131 | // MinConnectionIDLenInitial is the minimum length of the destination connection ID on an Initial packet. 132 | const MinConnectionIDLenInitial = 8 133 | 134 | // DefaultAckDelayExponent is the default ack delay exponent 135 | const DefaultAckDelayExponent = 3 136 | 137 | // DefaultActiveConnectionIDLimit is the default active connection ID limit 138 | const DefaultActiveConnectionIDLimit = 2 139 | 140 | // MaxAckDelayExponent is the maximum ack delay exponent 141 | const MaxAckDelayExponent = 20 142 | 143 | // DefaultMaxAckDelay is the default max_ack_delay 144 | const DefaultMaxAckDelay = 25 * time.Millisecond 145 | 146 | // MaxMaxAckDelay is the maximum max_ack_delay 147 | const MaxMaxAckDelay = (1<<14 - 1) * time.Millisecond 148 | 149 | // MaxConnIDLen is the maximum length of the connection ID 150 | const MaxConnIDLen = 20 151 | 152 | // InvalidPacketLimitAES is the maximum number of packets that we can fail to decrypt when using 153 | // AEAD_AES_128_GCM or AEAD_AES_265_GCM. 154 | const InvalidPacketLimitAES = 1 << 52 155 | 156 | // InvalidPacketLimitChaCha is the maximum number of packets that we can fail to decrypt when using AEAD_CHACHA20_POLY1305. 157 | const InvalidPacketLimitChaCha = 1 << 36 158 | -------------------------------------------------------------------------------- /internal/quicvarint/varint.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The quic-go Authors. All rights reserved. 2 | // Use of this source code is governed by a MIT-style 3 | // license that can be found in the LICENSE file of 4 | // the quic-go repository. 5 | 6 | package quicvarint 7 | 8 | import ( 9 | "fmt" 10 | "io" 11 | 12 | "github.com/refraction-networking/utls/internal/quicvarint/protocol" 13 | ) 14 | 15 | // taken from the QUIC draft 16 | const ( 17 | // Min is the minimum value allowed for a QUIC varint. 18 | Min = 0 19 | 20 | // Max is the maximum allowed value for a QUIC varint (2^62-1). 21 | Max = maxVarInt8 22 | 23 | maxVarInt1 = 63 24 | maxVarInt2 = 16383 25 | maxVarInt4 = 1073741823 26 | maxVarInt8 = 4611686018427387903 27 | ) 28 | 29 | // Read reads a number in the QUIC varint format from r. 30 | func Read(r io.ByteReader) (uint64, error) { 31 | firstByte, err := r.ReadByte() 32 | if err != nil { 33 | return 0, err 34 | } 35 | // the first two bits of the first byte encode the length 36 | len := 1 << ((firstByte & 0xc0) >> 6) 37 | b1 := firstByte & (0xff - 0xc0) 38 | if len == 1 { 39 | return uint64(b1), nil 40 | } 41 | b2, err := r.ReadByte() 42 | if err != nil { 43 | return 0, err 44 | } 45 | if len == 2 { 46 | return uint64(b2) + uint64(b1)<<8, nil 47 | } 48 | b3, err := r.ReadByte() 49 | if err != nil { 50 | return 0, err 51 | } 52 | b4, err := r.ReadByte() 53 | if err != nil { 54 | return 0, err 55 | } 56 | if len == 4 { 57 | return uint64(b4) + uint64(b3)<<8 + uint64(b2)<<16 + uint64(b1)<<24, nil 58 | } 59 | b5, err := r.ReadByte() 60 | if err != nil { 61 | return 0, err 62 | } 63 | b6, err := r.ReadByte() 64 | if err != nil { 65 | return 0, err 66 | } 67 | b7, err := r.ReadByte() 68 | if err != nil { 69 | return 0, err 70 | } 71 | b8, err := r.ReadByte() 72 | if err != nil { 73 | return 0, err 74 | } 75 | return uint64(b8) + uint64(b7)<<8 + uint64(b6)<<16 + uint64(b5)<<24 + uint64(b4)<<32 + uint64(b3)<<40 + uint64(b2)<<48 + uint64(b1)<<56, nil 76 | } 77 | 78 | // Append appends i in the QUIC varint format. 79 | func Append(b []byte, i uint64) []byte { 80 | if i <= maxVarInt1 { 81 | return append(b, uint8(i)) 82 | } 83 | if i <= maxVarInt2 { 84 | return append(b, []byte{uint8(i>>8) | 0x40, uint8(i)}...) 85 | } 86 | if i <= maxVarInt4 { 87 | return append(b, []byte{uint8(i>>24) | 0x80, uint8(i >> 16), uint8(i >> 8), uint8(i)}...) 88 | } 89 | if i <= maxVarInt8 { 90 | return append(b, []byte{ 91 | uint8(i>>56) | 0xc0, uint8(i >> 48), uint8(i >> 40), uint8(i >> 32), 92 | uint8(i >> 24), uint8(i >> 16), uint8(i >> 8), uint8(i), 93 | }...) 94 | } 95 | panic(fmt.Sprintf("%#x doesn't fit into 62 bits", i)) 96 | } 97 | 98 | // AppendWithLen append i in the QUIC varint format with the desired length. 99 | func AppendWithLen(b []byte, i uint64, length protocol.ByteCount) []byte { 100 | if length != 1 && length != 2 && length != 4 && length != 8 { 101 | panic("invalid varint length") 102 | } 103 | l := Len(i) 104 | if l == length { 105 | return Append(b, i) 106 | } 107 | if l > length { 108 | panic(fmt.Sprintf("cannot encode %d in %d bytes", i, length)) 109 | } 110 | if length == 2 { 111 | b = append(b, 0b01000000) 112 | } else if length == 4 { 113 | b = append(b, 0b10000000) 114 | } else if length == 8 { 115 | b = append(b, 0b11000000) 116 | } 117 | for j := protocol.ByteCount(1); j < length-l; j++ { 118 | b = append(b, 0) 119 | } 120 | for j := protocol.ByteCount(0); j < l; j++ { 121 | b = append(b, uint8(i>>(8*(l-1-j)))) 122 | } 123 | return b 124 | } 125 | 126 | // Len determines the number of bytes that will be needed to write the number i. 127 | func Len(i uint64) protocol.ByteCount { 128 | if i <= maxVarInt1 { 129 | return 1 130 | } 131 | if i <= maxVarInt2 { 132 | return 2 133 | } 134 | if i <= maxVarInt4 { 135 | return 4 136 | } 137 | if i <= maxVarInt8 { 138 | return 8 139 | } 140 | // Don't use a fmt.Sprintf here to format the error message. 141 | // The function would then exceed the inlining budget. 142 | panic(struct { 143 | message string 144 | num uint64 145 | }{"value doesn't fit into 62 bits: ", i}) 146 | } 147 | -------------------------------------------------------------------------------- /internal/tls12/tls12.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. 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 tls12 6 | 7 | import ( 8 | "crypto/hmac" 9 | "hash" 10 | ) 11 | 12 | // PRF implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, 13 | // Section 5 and allowed by SP 800-135, Revision 1, Section 4.2.2. 14 | func PRF(hash func() hash.Hash, secret []byte, label string, seed []byte, keyLen int) []byte { 15 | labelAndSeed := make([]byte, len(label)+len(seed)) 16 | copy(labelAndSeed, label) 17 | copy(labelAndSeed[len(label):], seed) 18 | 19 | result := make([]byte, keyLen) 20 | pHash(hash, result, secret, labelAndSeed) 21 | return result 22 | } 23 | 24 | // pHash implements the P_hash function, as defined in RFC 5246, Section 5. 25 | func pHash(hash func() hash.Hash, result, secret, seed []byte) { 26 | h := hmac.New(hash, secret) 27 | h.Write(seed) 28 | a := h.Sum(nil) 29 | 30 | for len(result) > 0 { 31 | h.Reset() 32 | h.Write(a) 33 | h.Write(seed) 34 | b := h.Sum(nil) 35 | n := copy(result, b) 36 | result = result[n:] 37 | 38 | h.Reset() 39 | h.Write(a) 40 | a = h.Sum(nil) 41 | } 42 | } 43 | 44 | const masterSecretLength = 48 45 | const extendedMasterSecretLabel = "extended master secret" 46 | 47 | // MasterSecret implements the TLS 1.2 extended master secret derivation, as 48 | // defined in RFC 7627 and allowed by SP 800-135, Revision 1, Section 4.2.2. 49 | func MasterSecret(hash func() hash.Hash, preMasterSecret, transcript []byte) []byte { 50 | // [uTLS SECTION BEGIN] 51 | // "The TLS 1.2 KDF is an approved KDF when the following conditions are 52 | // satisfied: [...] (3) P_HASH uses either SHA-256, SHA-384 or SHA-512." 53 | // h := hash() 54 | // switch any(h).(type) { 55 | // case *sha256.Digest: 56 | // if h.Size() != 32 { 57 | // fips140.RecordNonApproved() 58 | // } 59 | // case *sha512.Digest: 60 | // if h.Size() != 46 && h.Size() != 64 { 61 | // fips140.RecordNonApproved() 62 | // } 63 | // default: 64 | // fips140.RecordNonApproved() 65 | // } 66 | // [uTLS SECTION END] 67 | 68 | return PRF(hash, preMasterSecret, extendedMasterSecretLabel, transcript, masterSecretLength) 69 | } 70 | -------------------------------------------------------------------------------- /internal/tls13/u_tls13.go: -------------------------------------------------------------------------------- 1 | package tls13 2 | 3 | import fips140 "hash" 4 | 5 | func NewEarlySecretFromSecret[H fips140.Hash](hash func() H, secret []byte) *EarlySecret { 6 | return &EarlySecret{ 7 | secret: secret, 8 | hash: func() fips140.Hash { return hash() }, 9 | } 10 | } 11 | 12 | func (s *EarlySecret) Secret() []byte { 13 | if s != nil { 14 | return s.secret 15 | } 16 | return nil 17 | } 18 | 19 | func NewMasterSecretFromSecret[H fips140.Hash](hash func() H, secret []byte) *MasterSecret { 20 | return &MasterSecret{ 21 | secret: secret, 22 | hash: func() fips140.Hash { return hash() }, 23 | } 24 | } 25 | 26 | func (s *MasterSecret) Secret() []byte { 27 | if s != nil { 28 | return s.secret 29 | } 30 | return nil 31 | } 32 | -------------------------------------------------------------------------------- /key_schedule.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. 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/ecdh" 9 | "crypto/hmac" 10 | "crypto/mlkem" 11 | "errors" 12 | "hash" 13 | "io" 14 | 15 | "github.com/refraction-networking/utls/internal/tls13" 16 | ) 17 | 18 | // This file contains the functions necessary to compute the TLS 1.3 key 19 | // schedule. See RFC 8446, Section 7. 20 | 21 | // nextTrafficSecret generates the next traffic secret, given the current one, 22 | // according to RFC 8446, Section 7.2. 23 | func (c *cipherSuiteTLS13) nextTrafficSecret(trafficSecret []byte) []byte { 24 | return tls13.ExpandLabel(c.hash.New, trafficSecret, "traffic upd", nil, c.hash.Size()) 25 | } 26 | 27 | // trafficKey generates traffic keys according to RFC 8446, Section 7.3. 28 | func (c *cipherSuiteTLS13) trafficKey(trafficSecret []byte) (key, iv []byte) { 29 | key = tls13.ExpandLabel(c.hash.New, trafficSecret, "key", nil, c.keyLen) 30 | iv = tls13.ExpandLabel(c.hash.New, trafficSecret, "iv", nil, aeadNonceLength) 31 | return 32 | } 33 | 34 | // finishedHash generates the Finished verify_data or PskBinderEntry according 35 | // to RFC 8446, Section 4.4.4. See sections 4.4 and 4.2.11.2 for the baseKey 36 | // selection. 37 | func (c *cipherSuiteTLS13) finishedHash(baseKey []byte, transcript hash.Hash) []byte { 38 | finishedKey := tls13.ExpandLabel(c.hash.New, baseKey, "finished", nil, c.hash.Size()) 39 | verifyData := hmac.New(c.hash.New, finishedKey) 40 | verifyData.Write(transcript.Sum(nil)) 41 | return verifyData.Sum(nil) 42 | } 43 | 44 | // exportKeyingMaterial implements RFC5705 exporters for TLS 1.3 according to 45 | // RFC 8446, Section 7.5. 46 | func (c *cipherSuiteTLS13) exportKeyingMaterial(s *tls13.MasterSecret, transcript hash.Hash) func(string, []byte, int) ([]byte, error) { 47 | expMasterSecret := s.ExporterMasterSecret(transcript) 48 | return func(label string, context []byte, length int) ([]byte, error) { 49 | return expMasterSecret.Exporter(label, context, length), nil 50 | } 51 | } 52 | 53 | type keySharePrivateKeys struct { 54 | curveID CurveID 55 | ecdhe *ecdh.PrivateKey 56 | mlkem *mlkem.DecapsulationKey768 57 | mlkemEcdhe *ecdh.PrivateKey // [uTLS] seperate ecdhe key for pq keyshare in line with Chrome, instead of reusing ecdhe key like stdlib 58 | } 59 | 60 | const x25519PublicKeySize = 32 61 | 62 | // generateECDHEKey returns a PrivateKey that implements Diffie-Hellman 63 | // according to RFC 8446, Section 4.2.8.2. 64 | func generateECDHEKey(rand io.Reader, curveID CurveID) (*ecdh.PrivateKey, error) { 65 | curve, ok := curveForCurveID(curveID) 66 | if !ok { 67 | return nil, errors.New("tls: internal error: unsupported curve") 68 | } 69 | 70 | return curve.GenerateKey(rand) 71 | } 72 | 73 | func curveForCurveID(id CurveID) (ecdh.Curve, bool) { 74 | switch id { 75 | case X25519: 76 | return ecdh.X25519(), true 77 | case CurveP256: 78 | return ecdh.P256(), true 79 | case CurveP384: 80 | return ecdh.P384(), true 81 | case CurveP521: 82 | return ecdh.P521(), true 83 | default: 84 | return nil, false 85 | } 86 | } 87 | 88 | func curveIDForCurve(curve ecdh.Curve) (CurveID, bool) { 89 | switch curve { 90 | case ecdh.X25519(): 91 | return X25519, true 92 | case ecdh.P256(): 93 | return CurveP256, true 94 | case ecdh.P384(): 95 | return CurveP384, true 96 | case ecdh.P521(): 97 | return CurveP521, true 98 | default: 99 | return 0, false 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /key_schedule_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. 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 | "crypto/sha256" 10 | "encoding/hex" 11 | "strings" 12 | "testing" 13 | "unicode" 14 | 15 | "github.com/refraction-networking/utls/internal/tls13" 16 | ) 17 | 18 | func TestACVPVectors(t *testing.T) { 19 | // https://github.com/usnistgov/ACVP-Server/blob/3a7333f63/gen-val/json-files/TLS-v1.3-KDF-RFC8446/prompt.json#L428-L436 20 | psk := fromHex("56288B726C73829F7A3E47B103837C8139ACF552E7530C7A710B35ED41191698") 21 | dhe := fromHex("EFFE9EC26AA29FD750DFA6A10B944D74071595B27EE88887D5E11C84590B5CC3") 22 | helloClientRandom := fromHex("E9137679E582BA7C1DB41CF725F86C6D09C8C05F297BAD9A65B552EAF524FDE4") 23 | helloServerRandom := fromHex("23ECCFD030790748C8F8D8A656FD98D717F1B62AF3712F97211D2070B499F98A") 24 | finishedClientRandom := fromHex("62A62FA75563ED4FDCAA0BC16567B314871C304ACF06B0FFC3F08C1797594D43") 25 | finishedServerRandom := fromHex("C750EDA6696CD101B142BD79E00E6AC8C5F2C0ABC78DD64F4D991326659E9299") 26 | 27 | // https://github.com/usnistgov/ACVP-Server/blob/3a7333f63/gen-val/json-files/TLS-v1.3-KDF-RFC8446/expectedResults.json#L571-L581 28 | clientEarlyTrafficSecret := fromHex("3272189698C3594D18F58EFA3F12B638A249515099BE7A2FA9836BABE74F0111") 29 | earlyExporterMasterSecret := fromHex("88E078F562CDC930219F6A5E98A1CE8C6E5F3DAC5AC516459A96F2EF8F114C66") 30 | clientHandshakeTrafficSecret := fromHex("B32306C3CE9932C460A1FE6C0F060593974842036B96FA45049B7352E71C2AD2") 31 | serverHandshakeTrafficSecret := fromHex("22787F8CA269D34BC549AC8BA19F2040938A3AA370D7CC9D60F720882B88D01B") 32 | clientApplicationTrafficSecret := fromHex("47D7EA08397B5871154B0FE85584BCC30A87C69E84D69B56007C5B21F76493BA") 33 | serverApplicationTrafficSecret := fromHex("EFBDB0C873C0480DA57307083839A8984BE25B9A8545E4FCA029940FE2800565") 34 | exporterMasterSecret := fromHex("8A43D787EE3804EAD4A2A5B32972F9896B696295645D7222E1FD081DDD939834") 35 | resumptionMasterSecret := fromHex("5F4C961329C91044011ACBECB0B289282E0E3FED045CB3EA924DFFE5FE654B3D") 36 | 37 | // The "Random" values are undocumented, but they are meant to be written to 38 | // the hash in sequence to develop the transcript. 39 | transcript := sha256.New() 40 | 41 | es := tls13.NewEarlySecret(sha256.New, psk) 42 | 43 | transcript.Write(helloClientRandom) 44 | 45 | if got := es.ClientEarlyTrafficSecret(transcript); !bytes.Equal(got, clientEarlyTrafficSecret) { 46 | t.Errorf("clientEarlyTrafficSecret = %x, want %x", got, clientEarlyTrafficSecret) 47 | } 48 | if got := tls13.TestingOnlyExporterSecret(es.EarlyExporterMasterSecret(transcript)); !bytes.Equal(got, earlyExporterMasterSecret) { 49 | t.Errorf("earlyExporterMasterSecret = %x, want %x", got, earlyExporterMasterSecret) 50 | } 51 | 52 | hs := es.HandshakeSecret(dhe) 53 | 54 | transcript.Write(helloServerRandom) 55 | 56 | if got := hs.ClientHandshakeTrafficSecret(transcript); !bytes.Equal(got, clientHandshakeTrafficSecret) { 57 | t.Errorf("clientHandshakeTrafficSecret = %x, want %x", got, clientHandshakeTrafficSecret) 58 | } 59 | if got := hs.ServerHandshakeTrafficSecret(transcript); !bytes.Equal(got, serverHandshakeTrafficSecret) { 60 | t.Errorf("serverHandshakeTrafficSecret = %x, want %x", got, serverHandshakeTrafficSecret) 61 | } 62 | 63 | ms := hs.MasterSecret() 64 | 65 | transcript.Write(finishedServerRandom) 66 | 67 | if got := ms.ClientApplicationTrafficSecret(transcript); !bytes.Equal(got, clientApplicationTrafficSecret) { 68 | t.Errorf("clientApplicationTrafficSecret = %x, want %x", got, clientApplicationTrafficSecret) 69 | } 70 | if got := ms.ServerApplicationTrafficSecret(transcript); !bytes.Equal(got, serverApplicationTrafficSecret) { 71 | t.Errorf("serverApplicationTrafficSecret = %x, want %x", got, serverApplicationTrafficSecret) 72 | } 73 | if got := tls13.TestingOnlyExporterSecret(ms.ExporterMasterSecret(transcript)); !bytes.Equal(got, exporterMasterSecret) { 74 | t.Errorf("exporterMasterSecret = %x, want %x", got, exporterMasterSecret) 75 | } 76 | 77 | transcript.Write(finishedClientRandom) 78 | 79 | if got := ms.ResumptionMasterSecret(transcript); !bytes.Equal(got, resumptionMasterSecret) { 80 | t.Errorf("resumptionMasterSecret = %x, want %x", got, resumptionMasterSecret) 81 | } 82 | } 83 | 84 | // This file contains tests derived from draft-ietf-tls-tls13-vectors-07. 85 | 86 | func parseVector(v string) []byte { 87 | v = strings.Map(func(c rune) rune { 88 | if unicode.IsSpace(c) { 89 | return -1 90 | } 91 | return c 92 | }, v) 93 | parts := strings.Split(v, ":") 94 | v = parts[len(parts)-1] 95 | res, err := hex.DecodeString(v) 96 | if err != nil { 97 | panic(err) 98 | } 99 | return res 100 | } 101 | 102 | func TestTrafficKey(t *testing.T) { 103 | trafficSecret := parseVector( 104 | `PRK (32 octets): b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d 37 b4 105 | e9 c9 12 bc de d9 10 5d 42 be fd 59 d3 91 ad 38`) 106 | wantKey := parseVector( 107 | `key expanded (16 octets): 3f ce 51 60 09 c2 17 27 d0 f2 e4 e8 6e 108 | e4 03 bc`) 109 | wantIV := parseVector( 110 | `iv expanded (12 octets): 5d 31 3e b2 67 12 76 ee 13 00 0b 30`) 111 | 112 | c := cipherSuitesTLS13[0] 113 | gotKey, gotIV := c.trafficKey(trafficSecret) 114 | if !bytes.Equal(gotKey, wantKey) { 115 | t.Errorf("cipherSuiteTLS13.trafficKey() gotKey = % x, want % x", gotKey, wantKey) 116 | } 117 | if !bytes.Equal(gotIV, wantIV) { 118 | t.Errorf("cipherSuiteTLS13.trafficKey() gotIV = % x, want % x", gotIV, wantIV) 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /link_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Go Authors. 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 | "os" 10 | "os/exec" 11 | "path/filepath" 12 | "testing" 13 | 14 | "github.com/refraction-networking/utls/testenv" 15 | ) 16 | 17 | // Tests that the linker is able to remove references to the Client or Server if unused. 18 | func TestLinkerGC(t *testing.T) { 19 | if testing.Short() { 20 | t.Skip("skipping in short mode") 21 | } 22 | t.Parallel() 23 | goBin := testenv.GoToolPath(t) 24 | testenv.MustHaveGoBuild(t) 25 | 26 | tests := []struct { 27 | name string 28 | program string 29 | want []string 30 | bad []string 31 | }{ 32 | { 33 | name: "empty_import", 34 | program: `package main 35 | import _ "crypto/tls" 36 | func main() {} 37 | `, 38 | bad: []string{ 39 | "tls.(*Conn)", 40 | "type:crypto/tls.clientHandshakeState", 41 | "type:crypto/tls.serverHandshakeState", 42 | }, 43 | }, 44 | { 45 | name: "client_and_server", 46 | program: `package main 47 | import "crypto/tls" 48 | func main() { 49 | tls.Dial("", "", nil) 50 | tls.Server(nil, nil) 51 | } 52 | `, 53 | want: []string{ 54 | "crypto/tls.(*Conn).clientHandshake", 55 | "crypto/tls.(*Conn).serverHandshake", 56 | }, 57 | }, 58 | { 59 | name: "only_client", 60 | program: `package main 61 | import "crypto/tls" 62 | func main() { tls.Dial("", "", nil) } 63 | `, 64 | want: []string{ 65 | "crypto/tls.(*Conn).clientHandshake", 66 | }, 67 | bad: []string{ 68 | "crypto/tls.(*Conn).serverHandshake", 69 | }, 70 | }, 71 | // TODO: add only_server like func main() { tls.Server(nil, nil) } 72 | // That currently brings in the client via Conn.handleRenegotiation. 73 | 74 | } 75 | tmpDir := t.TempDir() 76 | goFile := filepath.Join(tmpDir, "x.go") 77 | exeFile := filepath.Join(tmpDir, "x.exe") 78 | for _, tt := range tests { 79 | t.Run(tt.name, func(t *testing.T) { 80 | if err := os.WriteFile(goFile, []byte(tt.program), 0644); err != nil { 81 | t.Fatal(err) 82 | } 83 | os.Remove(exeFile) 84 | cmd := exec.Command(goBin, "build", "-o", "x.exe", "x.go") 85 | cmd.Dir = tmpDir 86 | if out, err := cmd.CombinedOutput(); err != nil { 87 | t.Fatalf("compile: %v, %s", err, out) 88 | } 89 | 90 | cmd = exec.Command(goBin, "tool", "nm", "x.exe") 91 | cmd.Dir = tmpDir 92 | nm, err := cmd.CombinedOutput() 93 | if err != nil { 94 | t.Fatalf("nm: %v, %s", err, nm) 95 | } 96 | for _, sym := range tt.want { 97 | if !bytes.Contains(nm, []byte(sym)) { 98 | t.Errorf("expected symbol %q not found", sym) 99 | } 100 | } 101 | for _, sym := range tt.bad { 102 | if bytes.Contains(nm, []byte(sym)) { 103 | t.Errorf("unexpected symbol %q found", sym) 104 | } 105 | } 106 | }) 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refraction-networking/utls/41ce3ba2c2d77d9d4b784e72ffa1841653acc525/logo.png -------------------------------------------------------------------------------- /logo_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refraction-networking/utls/41ce3ba2c2d77d9d4b784e72ffa1841653acc525/logo_small.png -------------------------------------------------------------------------------- /testdata/Client-TLSv10-Ed25519: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refraction-networking/utls/41ce3ba2c2d77d9d4b784e72ffa1841653acc525/testdata/Client-TLSv10-Ed25519 -------------------------------------------------------------------------------- /testdata/Client-TLSv11-Ed25519: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refraction-networking/utls/41ce3ba2c2d77d9d4b784e72ffa1841653acc525/testdata/Client-TLSv11-Ed25519 -------------------------------------------------------------------------------- /testdata/Client-TLSv12-Ed25519: -------------------------------------------------------------------------------- 1 | >>> Flow 1 (client to server) 2 | 00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| 3 | 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 4 | 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 5 | 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 6 | 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| 7 | 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 8 | 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 9 | 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 10 | 00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 11 | 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 12 | 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| 13 | 000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| 14 | 000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| 15 | 000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| 16 | 000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| 17 | 000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| 18 | 00000100 cb 3b 74 |.;t| 19 | >>> Flow 2 (server to client) 20 | 00000000 16 03 03 00 5d 02 00 00 59 03 03 93 8a a3 77 84 |....]...Y.....w.| 21 | 00000010 fd 41 3d a5 ad b5 eb 91 63 a6 b5 3a 5f 21 08 df |.A=.....c..:_!..| 22 | 00000020 72 07 be 1f df d7 4e 6f f3 f8 cb 20 ae d3 e5 fe |r.....No... ....| 23 | 00000030 53 a3 c7 84 6c 3e c6 1d d5 65 5d a6 a5 7d f7 5c |S...l>...e]..}.\| 24 | 00000040 34 65 a7 df 1e 28 3f 7d 20 08 81 2c cc a9 00 00 |4e...(?} ..,....| 25 | 00000050 11 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 17 |................| 26 | 00000060 00 00 16 03 03 01 3c 0b 00 01 38 00 01 35 00 01 |......<...8..5..| 27 | 00000070 32 30 82 01 2e 30 81 e1 a0 03 02 01 02 02 10 0f |20...0..........| 28 | 00000080 43 1c 42 57 93 94 1d e9 87 e4 f1 ad 15 00 5d 30 |C.BW..........]0| 29 | 00000090 05 06 03 2b 65 70 30 12 31 10 30 0e 06 03 55 04 |...+ep0.1.0...U.| 30 | 000000a0 0a 13 07 41 63 6d 65 20 43 6f 30 1e 17 0d 31 39 |...Acme Co0...19| 31 | 000000b0 30 35 31 36 32 31 33 38 30 31 5a 17 0d 32 30 30 |0516213801Z..200| 32 | 000000c0 35 31 35 32 31 33 38 30 31 5a 30 12 31 10 30 0e |515213801Z0.1.0.| 33 | 000000d0 06 03 55 04 0a 13 07 41 63 6d 65 20 43 6f 30 2a |..U....Acme Co0*| 34 | 000000e0 30 05 06 03 2b 65 70 03 21 00 3f e2 15 2e e6 e3 |0...+ep.!.?.....| 35 | 000000f0 ef 3f 4e 85 4a 75 77 a3 64 9e ed e0 bf 84 2c cc |.?N.Juw.d.....,.| 36 | 00000100 92 26 8f fa 6f 34 83 aa ec 8f a3 4d 30 4b 30 0e |.&..o4.....M0K0.| 37 | 00000110 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 |..U...........0.| 38 | 00000120 06 03 55 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 |..U.%..0...+....| 39 | 00000130 07 03 01 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 |...0...U.......0| 40 | 00000140 00 30 16 06 03 55 1d 11 04 0f 30 0d 82 0b 65 78 |.0...U....0...ex| 41 | 00000150 61 6d 70 6c 65 2e 63 6f 6d 30 05 06 03 2b 65 70 |ample.com0...+ep| 42 | 00000160 03 41 00 63 44 ed 9c c4 be 53 24 53 9f d2 10 8d |.A.cD....S$S....| 43 | 00000170 9f e8 21 08 90 95 39 e5 0d c1 55 ff 2c 16 b7 1d |..!...9...U.,...| 44 | 00000180 fc ab 7d 4d d4 e0 93 13 d0 a9 42 e0 b6 6b fe 5d |..}M......B..k.]| 45 | 00000190 67 48 d7 9f 50 bc 6c cd 4b 03 83 7c f2 08 58 cd |gH..P.l.K..|..X.| 46 | 000001a0 ac cf 0c 16 03 03 00 6c 0c 00 00 68 03 00 1d 20 |.......l...h... | 47 | 000001b0 e9 e7 75 b4 4c 42 14 7a e0 50 0a 95 f1 d7 35 aa |..u.LB.z.P....5.| 48 | 000001c0 39 05 9e 59 73 5e cd d2 ec 56 18 f0 ee 1f 81 3c |9..Ys^...V.....<| 49 | 000001d0 08 07 00 40 44 e9 19 b6 00 49 f7 c8 06 62 cb c1 |...@D....I...b..| 50 | 000001e0 b5 7c b6 cd 32 47 c9 05 82 3b f0 af d1 cd 75 8b |.|..2G...;....u.| 51 | 000001f0 82 8b 47 dd 85 13 78 69 5d 40 7e 9b 91 24 2e ce |..G...xi]@~..$..| 52 | 00000200 3e be e0 12 1e ec 56 0b ff 25 21 92 6f 24 12 10 |>.....V..%!.o$..| 53 | 00000210 30 33 cf 04 16 03 03 00 04 0e 00 00 00 |03...........| 54 | >>> Flow 3 (client to server) 55 | 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 56 | 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 57 | 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| 58 | 00000030 16 03 03 00 20 69 ac be cf f1 3d 8a 4e f3 3a 54 |.... i....=.N.:T| 59 | 00000040 05 d8 20 3a f0 67 40 3f 5b 94 cf a4 3e ec 8e 4e |.. :.g@?[...>..N| 60 | 00000050 75 c9 92 2c af |u..,.| 61 | >>> Flow 4 (server to client) 62 | 00000000 14 03 03 00 01 01 16 03 03 00 20 70 c5 f8 c7 7c |.......... p...|| 63 | 00000010 4a 34 6f b0 eb 1b 13 c7 e0 21 32 cf ce 89 aa 53 |J4o......!2....S| 64 | 00000020 5f 67 b8 a7 3e 10 bb a3 5f fa 2f |_g..>..._./| 65 | >>> Flow 5 (client to server) 66 | 00000000 17 03 03 00 16 54 ae 8d 1c 04 40 47 8a 7e ac c3 |.....T....@G.~..| 67 | 00000010 21 a2 8a f0 5d 3d 12 9d b0 b5 8d 15 03 03 00 12 |!...]=..........| 68 | 00000020 71 3b 30 89 d4 c3 ef 34 66 92 29 1b e1 af d4 d2 |q;0....4f.).....| 69 | 00000030 7e cd |~.| 70 | -------------------------------------------------------------------------------- /testdata/Client-TLSv12-UTLS-AES128-GCM-SHA256-Firefox-55: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refraction-networking/utls/41ce3ba2c2d77d9d4b784e72ffa1841653acc525/testdata/Client-TLSv12-UTLS-AES128-GCM-SHA256-Firefox-55 -------------------------------------------------------------------------------- /testdata/Client-TLSv12-UTLS-ECDHE-ECDSA-AES128-GCM-SHA256-Chrome-58: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refraction-networking/utls/41ce3ba2c2d77d9d4b784e72ffa1841653acc525/testdata/Client-TLSv12-UTLS-ECDHE-ECDSA-AES128-GCM-SHA256-Chrome-58 -------------------------------------------------------------------------------- /testdata/Client-TLSv12-UTLS-ECDHE-ECDSA-AES128-GCM-SHA256-Chrome-58setclienthello: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refraction-networking/utls/41ce3ba2c2d77d9d4b784e72ffa1841653acc525/testdata/Client-TLSv12-UTLS-ECDHE-ECDSA-AES128-GCM-SHA256-Chrome-58setclienthello -------------------------------------------------------------------------------- /testdata/Client-TLSv12-UTLS-ECDHE-ECDSA-AES128-GCM-SHA256-Chrome-70: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refraction-networking/utls/41ce3ba2c2d77d9d4b784e72ffa1841653acc525/testdata/Client-TLSv12-UTLS-ECDHE-ECDSA-AES128-GCM-SHA256-Chrome-70 -------------------------------------------------------------------------------- /testdata/Client-TLSv12-UTLS-ECDHE-ECDSA-AES256-GCM-SHA256-Chrome-70: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refraction-networking/utls/41ce3ba2c2d77d9d4b784e72ffa1841653acc525/testdata/Client-TLSv12-UTLS-ECDHE-ECDSA-AES256-GCM-SHA256-Chrome-70 -------------------------------------------------------------------------------- /testdata/Client-TLSv13-Ed25519: -------------------------------------------------------------------------------- 1 | >>> Flow 1 (client to server) 2 | 00000000 16 03 01 00 fe 01 00 00 fa 03 03 00 00 00 00 00 |................| 3 | 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 4 | 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 5 | 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 6 | 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| 7 | 00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| 8 | 00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| 9 | 00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 10 | 00000080 01 00 00 7f 00 0b 00 02 01 00 ff 01 00 01 00 00 |................| 11 | 00000090 17 00 00 00 12 00 00 00 05 00 05 01 00 00 00 00 |................| 12 | 000000a0 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0d |................| 13 | 000000b0 00 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 |................| 14 | 000000c0 05 01 06 01 05 03 06 03 02 01 02 03 00 2b 00 09 |.............+..| 15 | 000000d0 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24 00 |..........3.&.$.| 16 | 000000e0 1d 00 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f |.. /.}.G.bC.(.._| 17 | 000000f0 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| 18 | 00000100 cb 3b 74 |.;t| 19 | >>> Flow 2 (server to client) 20 | 00000000 16 03 03 00 7a 02 00 00 76 03 03 b2 4d aa 76 5b |....z...v...M.v[| 21 | 00000010 b7 38 95 18 e6 81 66 f8 27 82 26 2c b3 44 50 b0 |.8....f.'.&,.DP.| 22 | 00000020 f4 a8 f5 f2 87 f0 9d 85 4f ac 60 20 00 00 00 00 |........O.` ....| 23 | 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 24 | 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| 25 | 00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 e7 |..+.....3.$... .| 26 | 00000060 c2 3e 68 73 d9 fd 6e 69 16 15 85 84 24 45 36 47 |.>hs..ni....$E6G| 27 | 00000070 1b ad d9 c4 dc 4a 61 c6 12 5c 22 bf 1e 2f 59 14 |.....Ja..\"../Y.| 28 | 00000080 03 03 00 01 01 17 03 03 00 17 0f a4 05 81 10 48 |...............H| 29 | 00000090 c7 b7 78 9b 56 14 6c 9f 55 28 e3 4c 42 80 cc 1c |..x.V.l.U(.LB...| 30 | 000000a0 31 17 03 03 01 50 0d af 3b 08 02 84 89 42 b5 75 |1....P..;....B.u| 31 | 000000b0 c5 8f 9f c2 b1 dc cb 7c 6a d5 31 41 9a 16 8f fa |.......|j.1A....| 32 | 000000c0 74 40 21 5d f9 cc b0 1d 30 80 87 9a b2 57 58 53 |t@!]....0....WXS| 33 | 000000d0 2c 9e 5c 97 20 9c 81 77 16 25 62 9b fc a4 e1 9a |,.\. ..w.%b.....| 34 | 000000e0 80 c8 9a 4c f6 fc ae 79 a5 c2 26 4b 55 41 ff d0 |...L...y..&KUA..| 35 | 000000f0 25 4b 70 c9 ad b6 04 80 65 19 e0 fe 05 e7 b4 dc |%Kp.....e.......| 36 | 00000100 53 8f f8 3b ed 2c df b9 08 c2 da 60 b9 23 17 50 |S..;.,.....`.#.P| 37 | 00000110 da 0f 24 76 15 21 e6 e9 a8 f5 3e 08 cc 1b ee 92 |..$v.!....>.....| 38 | 00000120 2b 01 92 8d f9 4f 5a 3a 53 11 fc 32 52 cc af cd |+....OZ:S..2R...| 39 | 00000130 7b 94 0e 76 10 c2 16 36 2d a4 64 69 1c 05 70 20 |{..v...6-.di..p | 40 | 00000140 0d 23 cd 4a 33 c5 c7 db db 0f f8 b6 42 0c 83 0a |.#.J3.......B...| 41 | 00000150 a1 73 68 fb 87 2c 9d d2 d3 cf d7 3a bb 36 7e 83 |.sh..,.....:.6~.| 42 | 00000160 c3 3f bc e2 61 d9 c2 8b 15 a2 cc bf 14 a0 69 f4 |.?..a.........i.| 43 | 00000170 22 02 a9 ff 5e 55 37 6e 61 86 71 73 94 2f 7e 50 |"...^U7na.qs./~P| 44 | 00000180 45 96 cf 23 dd 39 90 5d 57 04 a3 d0 9f 97 f8 56 |E..#.9.]W......V| 45 | 00000190 fa cf 7a a9 e6 57 1f cb 33 a0 82 7a 84 94 1f 6d |..z..W..3..z...m| 46 | 000001a0 d8 0b c7 fb bc 62 94 36 4a d6 96 ce f6 f2 7f 06 |.....b.6J.......| 47 | 000001b0 18 59 66 77 77 12 8c 74 06 61 8f b6 37 35 65 fd |.Yfww..t.a..75e.| 48 | 000001c0 f1 0b fe e6 cc a9 64 f5 b5 0d 06 4e 38 4b 4b 78 |......d....N8KKx| 49 | 000001d0 be 6a cc 67 9e 39 f8 f2 27 33 a9 2d bc 9c 5e 06 |.j.g.9..'3.-..^.| 50 | 000001e0 b9 fb 76 0c be 8d 2a a5 6d cf 83 55 4f c5 6e 6e |..v...*.m..UO.nn| 51 | 000001f0 d0 08 8b f6 5a 61 17 03 03 00 59 c1 cc 58 14 33 |....Za....Y..X.3| 52 | 00000200 5a 39 b5 40 46 e8 b1 28 06 08 22 d3 27 b4 e6 ef |Z9.@F..(..".'...| 53 | 00000210 10 79 08 d4 ce 9e e2 cb 0b 86 a4 b1 80 e4 1b ac |.y..............| 54 | 00000220 71 15 fd 16 5b aa 01 c2 7b e3 c2 84 01 c0 f6 04 |q...[...{.......| 55 | 00000230 a7 31 2b ec f2 50 bf 5a 07 6f b8 03 9f d2 c6 ad |.1+..P.Z.o......| 56 | 00000240 73 18 81 f5 fd 9a 5a b2 bc 9f 85 94 9f f6 da da |s.....Z.........| 57 | 00000250 dd 56 bc 66 17 03 03 00 35 9f 7e 2e 02 66 bb ac |.V.f....5.~..f..| 58 | 00000260 3d d8 92 70 c9 35 c6 df ff 0f 81 b5 ca d4 56 4a |=..p.5........VJ| 59 | 00000270 24 06 06 57 28 e9 9d 82 0e 40 06 a7 f8 cc bc 6c |$..W(....@.....l| 60 | 00000280 a2 ea 2b 0e 88 77 05 de 3d 30 a0 6f bc 98 |..+..w..=0.o..| 61 | >>> Flow 3 (client to server) 62 | 00000000 14 03 03 00 01 01 17 03 03 00 35 1c 60 8f 01 6b |..........5.`..k| 63 | 00000010 7c e3 d4 28 24 d8 7c 85 7f 63 44 23 97 7c a0 de ||..($.|..cD#.|..| 64 | 00000020 70 61 9e d9 ce 35 d9 3b 81 68 09 12 c1 b9 5e f5 |pa...5.;.h....^.| 65 | 00000030 32 23 9b 47 fc be 74 3c e6 1b 3f cd e8 c1 f1 4f |2#.G..t<..?....O| 66 | 00000040 17 03 03 00 17 1a 16 bc fe 99 30 d8 97 c1 00 d9 |..........0.....| 67 | 00000050 fd 1a 44 bd 84 35 dc 66 62 eb 28 3d 17 03 03 00 |..D..5.fb.(=....| 68 | 00000060 13 b4 8a 54 df ae 97 ce 2e ae fa 38 ca 02 a1 d6 |...T.......8....| 69 | 00000070 f5 40 64 2b |.@d+| 70 | -------------------------------------------------------------------------------- /testdata/ClientHello-JSON-Chrome102.json: -------------------------------------------------------------------------------- 1 | { 2 | "cipher_suites": [ 3 | "GREASE", 4 | "TLS_AES_128_GCM_SHA256", 5 | "TLS_AES_256_GCM_SHA384", 6 | "TLS_CHACHA20_POLY1305_SHA256", 7 | "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 8 | "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 9 | "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 10 | "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 11 | "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", 12 | "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", 13 | "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 14 | "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 15 | "TLS_RSA_WITH_AES_128_GCM_SHA256", 16 | "TLS_RSA_WITH_AES_256_GCM_SHA384", 17 | "TLS_RSA_WITH_AES_128_CBC_SHA", 18 | "TLS_RSA_WITH_AES_256_CBC_SHA" 19 | ], 20 | "compression_methods": [ 21 | "NULL" 22 | ], 23 | "extensions": [ 24 | {"name": "GREASE"}, 25 | {"name": "server_name"}, 26 | {"name": "extended_master_secret"}, 27 | {"name": "renegotiation_info"}, 28 | {"name": "supported_groups", "named_group_list": [ 29 | "GREASE", 30 | "x25519", 31 | "secp256r1", 32 | "secp384r1" 33 | ]}, 34 | {"name": "ec_point_formats", "ec_point_format_list": [ 35 | "uncompressed" 36 | ]}, 37 | {"name": "session_ticket"}, 38 | {"name": "application_layer_protocol_negotiation", "protocol_name_list": [ 39 | "h2", 40 | "http/1.1" 41 | ]}, 42 | {"name": "status_request"}, 43 | {"name": "signature_algorithms", "supported_signature_algorithms": [ 44 | "ecdsa_secp256r1_sha256", 45 | "rsa_pss_rsae_sha256", 46 | "rsa_pkcs1_sha256", 47 | "ecdsa_secp384r1_sha384", 48 | "rsa_pss_rsae_sha384", 49 | "rsa_pkcs1_sha384", 50 | "rsa_pss_rsae_sha512", 51 | "rsa_pkcs1_sha512" 52 | ]}, 53 | {"name": "signed_certificate_timestamp"}, 54 | {"name": "key_share", "client_shares": [ 55 | {"group": "GREASE", "key_exchange": [0]}, 56 | {"group": "x25519"} 57 | ]}, 58 | {"name": "psk_key_exchange_modes", "ke_modes": [ 59 | "psk_dhe_ke" 60 | ]}, 61 | {"name": "supported_versions", "versions": [ 62 | "GREASE", 63 | "TLS 1.3", 64 | "TLS 1.2" 65 | ]}, 66 | {"name": "compress_certificate", "algorithms": [ 67 | "brotli" 68 | ]}, 69 | {"name": "application_settings", "supported_protocols": [ 70 | "h2" 71 | ]}, 72 | {"name": "GREASE"}, 73 | {"name": "padding", "len": 0} 74 | ] 75 | } -------------------------------------------------------------------------------- /testdata/ClientHello-JSON-Edge106.json: -------------------------------------------------------------------------------- 1 | { 2 | "cipher_suites": [ 3 | "GREASE", 4 | "TLS_AES_128_GCM_SHA256", 5 | "TLS_AES_256_GCM_SHA384", 6 | "TLS_AES_256_GCM_SHA384", 7 | "TLS_CHACHA20_POLY1305_SHA256", 8 | "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 9 | "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 10 | "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 11 | "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 12 | "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", 13 | "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", 14 | "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 15 | "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 16 | "TLS_RSA_WITH_AES_128_GCM_SHA256", 17 | "TLS_RSA_WITH_AES_256_GCM_SHA384", 18 | "TLS_RSA_WITH_AES_128_CBC_SHA", 19 | "TLS_RSA_WITH_AES_256_CBC_SHA" 20 | ], 21 | "compression_methods": [ 22 | "NULL" 23 | ], 24 | "extensions": [ 25 | {"name": "GREASE"}, 26 | {"name": "server_name"}, 27 | {"name": "extended_master_secret"}, 28 | {"name": "renegotiation_info"}, 29 | {"name": "supported_groups", "named_group_list": [ 30 | "GREASE", 31 | "x25519", 32 | "secp256r1", 33 | "secp384r1" 34 | ]}, 35 | {"name": "ec_point_formats", "ec_point_format_list": [ 36 | "uncompressed" 37 | ]}, 38 | {"name": "session_ticket"}, 39 | {"name": "application_layer_protocol_negotiation", "protocol_name_list": [ 40 | "h2", 41 | "http/1.1" 42 | ]}, 43 | {"name": "status_request"}, 44 | {"name": "signature_algorithms", "supported_signature_algorithms": [ 45 | "ecdsa_secp256r1_sha256", 46 | "rsa_pss_rsae_sha256", 47 | "rsa_pkcs1_sha256", 48 | "ecdsa_secp384r1_sha384", 49 | "rsa_pss_rsae_sha384", 50 | "rsa_pkcs1_sha384", 51 | "rsa_pss_rsae_sha512", 52 | "rsa_pkcs1_sha512" 53 | ]}, 54 | {"name": "signed_certificate_timestamp"}, 55 | {"name": "key_share", "client_shares": [ 56 | {"group": "GREASE", "key_exchange": [0]}, 57 | {"group": "x25519"} 58 | ]}, 59 | {"name": "psk_key_exchange_modes", "ke_modes": [ 60 | "psk_dhe_ke" 61 | ]}, 62 | {"name": "supported_versions", "versions": [ 63 | "GREASE", 64 | "TLS 1.3", 65 | "TLS 1.2" 66 | ]}, 67 | {"name": "compress_certificate", "algorithms": [ 68 | "brotli" 69 | ]}, 70 | {"name": "application_settings", "supported_protocols": [ 71 | "h2" 72 | ]}, 73 | {"name": "GREASE"}, 74 | {"name": "padding", "len": 0} 75 | ] 76 | } -------------------------------------------------------------------------------- /testdata/ClientHello-JSON-Firefox105.json: -------------------------------------------------------------------------------- 1 | { 2 | "cipher_suites": [ 3 | "TLS_AES_128_GCM_SHA256", 4 | "TLS_CHACHA20_POLY1305_SHA256", 5 | "TLS_AES_256_GCM_SHA384", 6 | "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 7 | "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 8 | "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", 9 | "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", 10 | "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 11 | "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 12 | "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 13 | "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 14 | "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 15 | "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 16 | "TLS_RSA_WITH_AES_128_GCM_SHA256", 17 | "TLS_RSA_WITH_AES_256_GCM_SHA384", 18 | "TLS_RSA_WITH_AES_128_CBC_SHA", 19 | "TLS_RSA_WITH_AES_256_CBC_SHA" 20 | ], 21 | "compression_methods": [ 22 | "NULL" 23 | ], 24 | "extensions": [ 25 | {"name": "server_name"}, 26 | {"name": "extended_master_secret"}, 27 | {"name": "renegotiation_info"}, 28 | {"name": "supported_groups", "named_group_list": [ 29 | "x25519", 30 | "secp256r1", 31 | "secp384r1", 32 | "secp521r1", 33 | "ffdhe2048", 34 | "ffdhe3072" 35 | ]}, 36 | {"name": "ec_point_formats", "ec_point_format_list": [ 37 | "uncompressed" 38 | ]}, 39 | {"name": "session_ticket"}, 40 | {"name": "application_layer_protocol_negotiation", "protocol_name_list": [ 41 | "h2", 42 | "http/1.1" 43 | ]}, 44 | {"name": "status_request"}, 45 | {"name": "delegated_credentials", "supported_signature_algorithms": [ 46 | "ecdsa_secp256r1_sha256", 47 | "ecdsa_secp384r1_sha384", 48 | "ecdsa_secp521r1_sha512", 49 | "ecdsa_sha1" 50 | ]}, 51 | {"name": "key_share", "client_shares": [ 52 | {"group": "x25519"}, 53 | {"group": "secp256r1"} 54 | ]}, 55 | {"name": "supported_versions", "versions": [ 56 | "TLS 1.3", 57 | "TLS 1.2" 58 | ]}, 59 | {"name": "signature_algorithms", "supported_signature_algorithms": [ 60 | "ecdsa_secp256r1_sha256", 61 | "ecdsa_secp384r1_sha384", 62 | "ecdsa_secp521r1_sha512", 63 | "rsa_pss_rsae_sha256", 64 | "rsa_pss_rsae_sha384", 65 | "rsa_pss_rsae_sha512", 66 | "rsa_pkcs1_sha256", 67 | "rsa_pkcs1_sha384", 68 | "rsa_pkcs1_sha512", 69 | "ecdsa_sha1", 70 | "rsa_pkcs1_sha1" 71 | ]}, 72 | {"name": "psk_key_exchange_modes", "ke_modes": [ 73 | "psk_dhe_ke" 74 | ]}, 75 | {"name": "record_size_limit", "record_size_limit": 16385}, 76 | {"name": "padding", "len": 0} 77 | ] 78 | } -------------------------------------------------------------------------------- /testdata/ClientHello-JSON-iOS14.json: -------------------------------------------------------------------------------- 1 | { 2 | "cipher_suites": [ 3 | "GREASE", 4 | "TLS_AES_128_GCM_SHA256", 5 | "TLS_AES_256_GCM_SHA384", 6 | "TLS_CHACHA20_POLY1305_SHA256", 7 | "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 8 | "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 9 | "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", 10 | "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 11 | "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 12 | "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", 13 | "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", 14 | "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 15 | "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 16 | "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 17 | "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", 18 | "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 19 | "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 20 | "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 21 | "TLS_RSA_WITH_AES_256_GCM_SHA384", 22 | "TLS_RSA_WITH_AES_128_GCM_SHA256", 23 | "TLS_RSA_WITH_AES_256_CBC_SHA256", 24 | "TLS_RSA_WITH_AES_128_CBC_SHA256", 25 | "TLS_RSA_WITH_AES_256_CBC_SHA", 26 | "TLS_RSA_WITH_AES_128_CBC_SHA", 27 | "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", 28 | "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", 29 | "TLS_RSA_WITH_3DES_EDE_CBC_SHA" 30 | ], 31 | "compression_methods": [ 32 | "NULL" 33 | ], 34 | "extensions": [ 35 | {"name": "GREASE"}, 36 | {"name": "server_name"}, 37 | {"name": "extended_master_secret"}, 38 | {"name": "renegotiation_info"}, 39 | {"name": "supported_groups", "named_group_list": [ 40 | "GREASE", 41 | "x25519", 42 | "secp256r1", 43 | "secp384r1", 44 | "secp521r1" 45 | ]}, 46 | {"name": "ec_point_formats", "ec_point_format_list": [ 47 | "uncompressed" 48 | ]}, 49 | {"name": "application_layer_protocol_negotiation", "protocol_name_list": [ 50 | "h2", 51 | "http/1.1" 52 | ]}, 53 | {"name": "status_request"}, 54 | {"name": "signature_algorithms", "supported_signature_algorithms": [ 55 | "ecdsa_secp256r1_sha256", 56 | "rsa_pss_rsae_sha256", 57 | "rsa_pkcs1_sha256", 58 | "ecdsa_secp384r1_sha384", 59 | "ecdsa_sha1", 60 | "rsa_pss_rsae_sha384", 61 | "rsa_pss_rsae_sha384", 62 | "rsa_pkcs1_sha384", 63 | "rsa_pss_rsae_sha512", 64 | "rsa_pkcs1_sha512", 65 | "rsa_pkcs1_sha1" 66 | ]}, 67 | {"name": "signed_certificate_timestamp"}, 68 | {"name": "key_share", "client_shares": [ 69 | {"group": "GREASE", "key_exchange": [0]}, 70 | {"group": "x25519"} 71 | ]}, 72 | {"name": "psk_key_exchange_modes", "ke_modes": [ 73 | "psk_dhe_ke" 74 | ]}, 75 | {"name": "supported_versions", "versions": [ 76 | "GREASE", 77 | "TLS 1.3", 78 | "TLS 1.2", 79 | "TLS 1.1", 80 | "TLS 1.0" 81 | ]}, 82 | {"name": "GREASE"}, 83 | {"name": "padding"} 84 | ] 85 | } -------------------------------------------------------------------------------- /testdata/Server-TLSv10-RSA-3DES: -------------------------------------------------------------------------------- 1 | >>> Flow 1 (client to server) 2 | 00000000 16 03 01 00 39 01 00 00 35 03 01 51 7a 48 8d de |....9...5..QzH..| 3 | 00000010 0b 30 0f 9a 91 56 30 20 30 dd bd 74 3b e2 d7 db |.0...V0 0..t;...| 4 | 00000020 46 3d bf 6f b6 ae 53 8a 7d 18 50 00 00 04 00 0a |F=.o..S.}.P.....| 5 | 00000030 00 ff 01 00 00 08 00 16 00 00 00 17 00 00 |..............| 6 | >>> Flow 2 (server to client) 7 | 00000000 16 03 01 00 35 02 00 00 31 03 01 00 00 00 00 00 |....5...1.......| 8 | 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 9 | 00000020 00 00 00 44 4f 57 4e 47 52 44 00 00 00 0a 00 00 |...DOWNGRD......| 10 | 00000030 09 ff 01 00 01 00 00 17 00 00 16 03 01 02 59 0b |..............Y.| 11 | 00000040 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..| 12 | 00000050 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.| 13 | 00000060 a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........| 14 | 00000070 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 |0.1.0...U....Go1| 15 | 00000080 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo| 16 | 00000090 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 30 |t0...16010100000| 17 | 000000a0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000| 18 | 000000b0 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |Z0.1.0...U....Go| 19 | 000000c0 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 9f |1.0...U....Go0..| 20 | 000000d0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 |0...*.H.........| 21 | 000000e0 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e 12 |...0.......F}...| 22 | 000000f0 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 |'.H..(!.~...]..R| 23 | 00000100 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 |E.z6G....B[.....| 24 | 00000110 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 |y.@.Om..+.....g.| 25 | 00000120 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 |...."8.J.ts+.4..| 26 | 00000130 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 |....t{.X.la<..A.| 27 | 00000140 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf |.++$#w[.;.u]. T.| 28 | 00000150 a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 |.c...$....P....C| 29 | 00000160 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 |...ub...R.......| 30 | 00000170 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 |..0..0...U......| 31 | 00000180 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 |.....0...U.%..0.| 32 | 00000190 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 |..+.........+...| 33 | 000001a0 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 |....0...U.......| 34 | 000001b0 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 |0.0...U.........| 35 | 000001c0 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 |.CC>I..m....`0..| 36 | 000001d0 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 7e |.U.#..0...H.IM.~| 37 | 000001e0 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d |.1......n{0...U.| 38 | 000001f0 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 |...0...example.g| 39 | 00000200 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 |olang0...*.H....| 40 | 00000210 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 |.........0.@+[P.| 41 | 00000220 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 |a...SX...(.X..8.| 42 | 00000230 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 |...1Z..f=C.-....| 43 | 00000240 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 |.. d8.$:....}.@ | 44 | 00000250 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c |._...a..v......\| 45 | 00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...| 46 | 00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.| 47 | 00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`| 48 | 00000290 84 5c 21 d3 3b e9 fa e7 16 03 01 00 04 0e 00 00 |.\!.;...........| 49 | 000002a0 00 |.| 50 | >>> Flow 3 (client to server) 51 | 00000000 16 03 01 00 86 10 00 00 82 00 80 54 53 e6 48 5d |...........TS.H]| 52 | 00000010 bb 47 19 7e ab 31 3b 4a c8 fb da 69 9d 74 b3 e1 |.G.~.1;J...i.t..| 53 | 00000020 dc 8c ea 36 f7 a1 06 68 52 79 c3 08 be b9 5c 1a |...6...hRy....\.| 54 | 00000030 80 cc 13 b8 7b b8 02 98 5e f8 50 47 a5 0d 37 dd |....{...^.PG..7.| 55 | 00000040 86 c5 69 9c 1c 1c 91 39 ea 80 dc d1 87 d3 f8 f6 |..i....9........| 56 | 00000050 84 c6 65 72 af 71 dc 98 56 9e bc e7 a9 9d 9b 31 |..er.q..V......1| 57 | 00000060 d0 c3 54 28 05 86 91 e4 03 40 f7 2a cb 07 13 41 |..T(.....@.*...A| 58 | 00000070 1e 30 0b b1 2d 52 ae 1f a1 6b a9 db c2 76 1d 4a |.0..-R...k...v.J| 59 | 00000080 a6 81 ba 3c cb e9 3a 6b f3 70 ed 14 03 01 00 01 |...<..:k.p......| 60 | 00000090 01 16 03 01 00 28 01 84 d8 e4 7a b1 11 3e 27 fb |.....(....z..>'.| 61 | 000000a0 66 10 1a db 20 fb 9e e3 f1 a5 a7 86 2f fd c9 d2 |f... ......./...| 62 | 000000b0 1c b8 a4 2b af 2b 66 fc ad 31 72 28 d7 1a |...+.+f..1r(..| 63 | >>> Flow 4 (server to client) 64 | 00000000 14 03 01 00 01 01 16 03 01 00 28 67 3d c4 e9 a6 |..........(g=...| 65 | 00000010 bb 99 57 90 eb fa 86 ee ab 00 08 61 2d c8 50 5b |..W........a-.P[| 66 | 00000020 83 9c ce 83 60 7a 89 33 90 b7 f9 31 e9 37 04 3d |....`z.3...1.7.=| 67 | 00000030 d6 01 44 17 03 01 00 18 0a 1c 6c 75 23 bc b2 e7 |..D.......lu#...| 68 | 00000040 30 2d 61 57 d3 a6 a2 72 6a 7a 2d 8a 7b fd 45 67 |0-aW...rjz-.{.Eg| 69 | 00000050 17 03 01 00 28 23 8b 77 dd a3 f2 b6 0e 59 40 3b |....(#.w.....Y@;| 70 | 00000060 4e 3a 1b 0c 11 2f 99 00 b9 e1 2c 11 89 53 fb 23 |N:.../....,..S.#| 71 | 00000070 fb 6c 60 71 db a8 43 a4 92 ad 68 24 e9 15 03 01 |.l`q..C...h$....| 72 | 00000080 00 18 24 19 84 35 13 29 ed 3a f0 57 a9 e1 b6 e9 |..$..5.).:.W....| 73 | 00000090 05 64 fe 46 c0 ca b1 88 12 a7 |.d.F......| 74 | -------------------------------------------------------------------------------- /testdata/Server-TLSv10-RSA-RC4: -------------------------------------------------------------------------------- 1 | >>> Flow 1 (client to server) 2 | 00000000 16 03 01 00 39 01 00 00 35 03 01 eb 78 34 78 f6 |....9...5...x4x.| 3 | 00000010 8f 87 2f ee 5e da ee 37 5d 0a d5 79 d5 0e db b1 |../.^..7]..y....| 4 | 00000020 b7 03 37 1f 2d ce 04 b9 2d 65 d7 00 00 04 00 05 |..7.-...-e......| 5 | 00000030 00 ff 01 00 00 08 00 16 00 00 00 17 00 00 |..............| 6 | >>> Flow 2 (server to client) 7 | 00000000 16 03 01 00 35 02 00 00 31 03 01 00 00 00 00 00 |....5...1.......| 8 | 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 9 | 00000020 00 00 00 44 4f 57 4e 47 52 44 00 00 00 05 00 00 |...DOWNGRD......| 10 | 00000030 09 ff 01 00 01 00 00 17 00 00 16 03 01 02 59 0b |..............Y.| 11 | 00000040 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..| 12 | 00000050 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.| 13 | 00000060 a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........| 14 | 00000070 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 |0.1.0...U....Go1| 15 | 00000080 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo| 16 | 00000090 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 30 |t0...16010100000| 17 | 000000a0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000| 18 | 000000b0 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |Z0.1.0...U....Go| 19 | 000000c0 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 9f |1.0...U....Go0..| 20 | 000000d0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 |0...*.H.........| 21 | 000000e0 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e 12 |...0.......F}...| 22 | 000000f0 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 |'.H..(!.~...]..R| 23 | 00000100 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 |E.z6G....B[.....| 24 | 00000110 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 |y.@.Om..+.....g.| 25 | 00000120 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 |...."8.J.ts+.4..| 26 | 00000130 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 |....t{.X.la<..A.| 27 | 00000140 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf |.++$#w[.;.u]. T.| 28 | 00000150 a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 |.c...$....P....C| 29 | 00000160 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 |...ub...R.......| 30 | 00000170 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 |..0..0...U......| 31 | 00000180 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 |.....0...U.%..0.| 32 | 00000190 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 |..+.........+...| 33 | 000001a0 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 |....0...U.......| 34 | 000001b0 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 |0.0...U.........| 35 | 000001c0 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 |.CC>I..m....`0..| 36 | 000001d0 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 7e |.U.#..0...H.IM.~| 37 | 000001e0 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d |.1......n{0...U.| 38 | 000001f0 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 |...0...example.g| 39 | 00000200 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 |olang0...*.H....| 40 | 00000210 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 |.........0.@+[P.| 41 | 00000220 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 |a...SX...(.X..8.| 42 | 00000230 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 |...1Z..f=C.-....| 43 | 00000240 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 |.. d8.$:....}.@ | 44 | 00000250 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c |._...a..v......\| 45 | 00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...| 46 | 00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.| 47 | 00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`| 48 | 00000290 84 5c 21 d3 3b e9 fa e7 16 03 01 00 04 0e 00 00 |.\!.;...........| 49 | 000002a0 00 |.| 50 | >>> Flow 3 (client to server) 51 | 00000000 16 03 01 00 86 10 00 00 82 00 80 d4 db 61 0b 26 |.............a.&| 52 | 00000010 06 af 94 37 9d fc 50 3f 50 4f 58 37 b9 b1 c2 d2 |...7..P?POX7....| 53 | 00000020 92 2b f5 c9 fe 7f 3d f4 32 e3 ee ba 46 ea e5 36 |.+....=.2...F..6| 54 | 00000030 9b fd c5 89 c9 14 45 e7 f7 ea 1a a9 63 c5 62 fb |......E.....c.b.| 55 | 00000040 34 c4 80 1e 59 60 39 d9 ca 68 3f 3f 1a f9 6a 14 |4...Y`9..h??..j.| 56 | 00000050 f7 c8 91 3b 7d eb cc b9 8c 42 f1 ef d8 0f cd 17 |...;}....B......| 57 | 00000060 64 f3 b8 30 6e 50 d4 23 bb 26 78 c3 fe f0 c4 42 |d..0nP.#.&x....B| 58 | 00000070 0a 89 90 fb 43 fe 7f 0f 06 82 e8 7f fb 42 dd 46 |....C........B.F| 59 | 00000080 fc 38 6e d0 14 05 41 b8 05 6b e7 14 03 01 00 01 |.8n...A..k......| 60 | 00000090 01 16 03 01 00 24 b4 bb 3e 8f 6b 91 43 c2 b9 16 |.....$..>.k.C...| 61 | 000000a0 59 ba 7d f9 89 a4 89 ce 12 c8 76 b0 e3 8f 36 03 |Y.}.......v...6.| 62 | 000000b0 f7 48 03 7e 4a fe e5 8e 88 91 |.H.~J.....| 63 | >>> Flow 4 (server to client) 64 | 00000000 14 03 01 00 01 01 16 03 01 00 24 06 5d 9f 70 98 |..........$.].p.| 65 | 00000010 8b 42 79 f1 ba 73 40 8e b3 f6 ff a1 45 57 c4 f3 |.By..s@.....EW..| 66 | 00000020 6d 00 4e b5 52 f5 3d 08 b4 57 33 74 ab 6f 62 17 |m.N.R.=..W3t.ob.| 67 | 00000030 03 01 00 21 6e 3a c7 a5 63 fb 81 78 10 9c 85 ab |...!n:..c..x....| 68 | 00000040 3d 3b 50 3a 12 0b c2 0f f5 7e a2 d3 f7 82 3c 7f |=;P:.....~....<.| 69 | 00000050 45 29 2c 1e eb 15 03 01 00 16 66 a4 bb 6d d1 fc |E),.......f..m..| 70 | 00000060 36 b2 a9 e7 e5 7a da a1 37 f1 cf fa 8f 0c 73 f5 |6....z..7.....s.| 71 | -------------------------------------------------------------------------------- /testdata/Server-TLSv11-FallbackSCSV: -------------------------------------------------------------------------------- 1 | >>> Flow 1 (client to server) 2 | 00000000 16 03 01 00 77 01 00 00 73 03 02 0a 6b c9 55 9d |....w...s...k.U.| 3 | 00000010 bf 4e 61 b2 0a c7 c6 96 9f eb 90 91 87 ca d3 d3 |.Na.............| 4 | 00000020 62 dc b6 b4 db ea 41 fe 43 3e a3 00 00 14 c0 0a |b.....A.C>......| 5 | 00000030 c0 14 00 39 c0 09 c0 13 00 33 00 35 00 2f 00 ff |...9.....3.5./..| 6 | 00000040 56 00 01 00 00 36 00 00 00 0e 00 0c 00 00 09 31 |V....6.........1| 7 | 00000050 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| 8 | 00000060 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| 9 | 00000070 00 23 00 00 00 16 00 00 00 17 00 00 |.#..........| 10 | >>> Flow 2 (server to client) 11 | 00000000 15 03 02 00 02 02 56 |......V| 12 | -------------------------------------------------------------------------------- /testdata/Server-TLSv11-RSA-RC4: -------------------------------------------------------------------------------- 1 | >>> Flow 1 (client to server) 2 | 00000000 16 03 01 00 39 01 00 00 35 03 02 ac 4f 36 f3 4c |....9...5...O6.L| 3 | 00000010 64 ae 8d fc 50 a3 e1 e4 70 5d ba 8c de de c8 07 |d...P...p]......| 4 | 00000020 70 24 8d bd c1 69 a3 0e ad 16 38 00 00 04 00 05 |p$...i....8.....| 5 | 00000030 00 ff 01 00 00 08 00 16 00 00 00 17 00 00 |..............| 6 | >>> Flow 2 (server to client) 7 | 00000000 16 03 02 00 35 02 00 00 31 03 02 00 00 00 00 00 |....5...1.......| 8 | 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 9 | 00000020 00 00 00 44 4f 57 4e 47 52 44 00 00 00 05 00 00 |...DOWNGRD......| 10 | 00000030 09 ff 01 00 01 00 00 17 00 00 16 03 02 02 59 0b |..............Y.| 11 | 00000040 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..| 12 | 00000050 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.| 13 | 00000060 a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........| 14 | 00000070 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 |0.1.0...U....Go1| 15 | 00000080 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo| 16 | 00000090 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 30 |t0...16010100000| 17 | 000000a0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000| 18 | 000000b0 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |Z0.1.0...U....Go| 19 | 000000c0 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 9f |1.0...U....Go0..| 20 | 000000d0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 |0...*.H.........| 21 | 000000e0 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e 12 |...0.......F}...| 22 | 000000f0 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 |'.H..(!.~...]..R| 23 | 00000100 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 |E.z6G....B[.....| 24 | 00000110 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 |y.@.Om..+.....g.| 25 | 00000120 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 |...."8.J.ts+.4..| 26 | 00000130 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 |....t{.X.la<..A.| 27 | 00000140 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf |.++$#w[.;.u]. T.| 28 | 00000150 a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 |.c...$....P....C| 29 | 00000160 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 |...ub...R.......| 30 | 00000170 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 |..0..0...U......| 31 | 00000180 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 |.....0...U.%..0.| 32 | 00000190 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 |..+.........+...| 33 | 000001a0 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 |....0...U.......| 34 | 000001b0 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 |0.0...U.........| 35 | 000001c0 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 |.CC>I..m....`0..| 36 | 000001d0 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 7e |.U.#..0...H.IM.~| 37 | 000001e0 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d |.1......n{0...U.| 38 | 000001f0 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 |...0...example.g| 39 | 00000200 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 |olang0...*.H....| 40 | 00000210 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 |.........0.@+[P.| 41 | 00000220 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 |a...SX...(.X..8.| 42 | 00000230 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 |...1Z..f=C.-....| 43 | 00000240 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 |.. d8.$:....}.@ | 44 | 00000250 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c |._...a..v......\| 45 | 00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...| 46 | 00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.| 47 | 00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`| 48 | 00000290 84 5c 21 d3 3b e9 fa e7 16 03 02 00 04 0e 00 00 |.\!.;...........| 49 | 000002a0 00 |.| 50 | >>> Flow 3 (client to server) 51 | 00000000 16 03 02 00 86 10 00 00 82 00 80 49 c4 5f 04 e0 |...........I._..| 52 | 00000010 63 96 72 bd c9 00 af 17 b1 59 b4 c7 40 a5 b7 b5 |c.r......Y..@...| 53 | 00000020 68 79 d2 7b b0 2a e7 06 7e 97 ad da d8 3f cb f8 |hy.{.*..~....?..| 54 | 00000030 7c b9 f1 9d be 49 7c 09 6a b0 25 49 9c 06 2a c3 ||....I|.j.%I..*.| 55 | 00000040 d5 0a ae cc cc 08 31 5d 14 82 06 a7 57 fc 66 9c |......1]....W.f.| 56 | 00000050 90 b7 be aa 15 46 2b aa ae fc 3a ce 3d 64 4e 80 |.....F+...:.=dN.| 57 | 00000060 90 3f 77 c6 60 cd 6b dc 69 c1 92 a9 1e 8e 30 6a |.?w.`.k.i.....0j| 58 | 00000070 34 a3 db 1a f5 a3 f9 ac 1c 07 4f be 38 d1 a5 61 |4.........O.8..a| 59 | 00000080 e5 5f 84 99 f0 87 40 dc b2 cc 05 14 03 02 00 01 |._....@.........| 60 | 00000090 01 16 03 02 00 24 eb d9 48 20 7b db 97 48 f2 c7 |.....$..H {..H..| 61 | 000000a0 bb c1 ef fa 74 44 d8 a1 55 63 f3 d0 90 ef f2 0b |....tD..Uc......| 62 | 000000b0 67 10 98 27 76 8a 70 78 0b df |g..'v.px..| 63 | >>> Flow 4 (server to client) 64 | 00000000 14 03 02 00 01 01 16 03 02 00 24 41 50 b9 88 0e |..........$AP...| 65 | 00000010 3f 27 36 f0 27 70 ca b8 bc 38 df e9 68 3e 29 cf |?'6.'p...8..h>).| 66 | 00000020 80 b5 e8 59 bd 52 45 b7 0d fa a7 6d 77 a0 9e 17 |...Y.RE....mw...| 67 | 00000030 03 02 00 21 94 2a 6a ca f0 b3 7e 1c d6 58 3f 64 |...!.*j...~..X?d| 68 | 00000040 ef 62 35 72 aa c6 84 7b 19 c6 07 0e 04 63 c4 14 |.b5r...{.....c..| 69 | 00000050 43 d8 73 ff 2f 15 03 02 00 16 5a 45 ba 51 95 c9 |C.s./.....ZE.Q..| 70 | 00000060 53 2a a6 b1 61 35 db 0a 7b f9 8e a9 fb 18 87 b1 |S*..a5..{.......| 71 | -------------------------------------------------------------------------------- /testdata/Server-TLSv12-ALPN-NoMatch: -------------------------------------------------------------------------------- 1 | >>> Flow 1 (client to server) 2 | 00000000 16 03 01 00 9d 01 00 00 99 03 03 24 15 a8 f2 f5 |...........$....| 3 | 00000010 53 02 78 f0 4c f7 82 3c 68 7d a0 b1 9a 0f 29 32 |S.x.L..>> Flow 2 (server to client) 14 | 00000000 15 03 03 00 02 02 78 |......x| 15 | -------------------------------------------------------------------------------- /testdata/Server-TLSv12-Ed25519: -------------------------------------------------------------------------------- 1 | >>> Flow 1 (client to server) 2 | 00000000 16 03 01 00 85 01 00 00 81 03 03 f3 04 e3 e7 a2 |................| 3 | 00000010 39 79 b2 9e 94 35 cf c3 a8 54 77 ab 96 72 b6 40 |9y...5...Tw..r.@| 4 | 00000020 de 59 6b cf d4 f5 f4 2c fd 7d f6 00 00 04 cc a9 |.Yk....,.}......| 5 | 00000030 00 ff 01 00 00 54 00 0b 00 04 03 00 01 02 00 0a |.....T..........| 6 | 00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| 7 | 00000050 00 00 00 17 00 00 00 0d 00 30 00 2e 04 03 05 03 |.........0......| 8 | 00000060 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| 9 | 00000070 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 01 |................| 10 | 00000080 03 02 02 02 04 02 05 02 06 02 |..........| 11 | >>> Flow 2 (server to client) 12 | 00000000 16 03 03 00 3b 02 00 00 37 03 03 00 00 00 00 00 |....;...7.......| 13 | 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 14 | 00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 cc a9 00 00 |...DOWNGRD......| 15 | 00000030 0f ff 01 00 01 00 00 17 00 00 00 0b 00 02 01 00 |................| 16 | 00000040 16 03 03 01 3c 0b 00 01 38 00 01 35 00 01 32 30 |....<...8..5..20| 17 | 00000050 82 01 2e 30 81 e1 a0 03 02 01 02 02 10 0f 43 1c |...0..........C.| 18 | 00000060 42 57 93 94 1d e9 87 e4 f1 ad 15 00 5d 30 05 06 |BW..........]0..| 19 | 00000070 03 2b 65 70 30 12 31 10 30 0e 06 03 55 04 0a 13 |.+ep0.1.0...U...| 20 | 00000080 07 41 63 6d 65 20 43 6f 30 1e 17 0d 31 39 30 35 |.Acme Co0...1905| 21 | 00000090 31 36 32 31 33 38 30 31 5a 17 0d 32 30 30 35 31 |16213801Z..20051| 22 | 000000a0 35 32 31 33 38 30 31 5a 30 12 31 10 30 0e 06 03 |5213801Z0.1.0...| 23 | 000000b0 55 04 0a 13 07 41 63 6d 65 20 43 6f 30 2a 30 05 |U....Acme Co0*0.| 24 | 000000c0 06 03 2b 65 70 03 21 00 3f e2 15 2e e6 e3 ef 3f |..+ep.!.?......?| 25 | 000000d0 4e 85 4a 75 77 a3 64 9e ed e0 bf 84 2c cc 92 26 |N.Juw.d.....,..&| 26 | 000000e0 8f fa 6f 34 83 aa ec 8f a3 4d 30 4b 30 0e 06 03 |..o4.....M0K0...| 27 | 000000f0 55 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 |U...........0...| 28 | 00000100 55 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 |U.%..0...+......| 29 | 00000110 01 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 |.0...U.......0.0| 30 | 00000120 16 06 03 55 1d 11 04 0f 30 0d 82 0b 65 78 61 6d |...U....0...exam| 31 | 00000130 70 6c 65 2e 63 6f 6d 30 05 06 03 2b 65 70 03 41 |ple.com0...+ep.A| 32 | 00000140 00 63 44 ed 9c c4 be 53 24 53 9f d2 10 8d 9f e8 |.cD....S$S......| 33 | 00000150 21 08 90 95 39 e5 0d c1 55 ff 2c 16 b7 1d fc ab |!...9...U.,.....| 34 | 00000160 7d 4d d4 e0 93 13 d0 a9 42 e0 b6 6b fe 5d 67 48 |}M......B..k.]gH| 35 | 00000170 d7 9f 50 bc 6c cd 4b 03 83 7c f2 08 58 cd ac cf |..P.l.K..|..X...| 36 | 00000180 0c 16 03 03 00 6c 0c 00 00 68 03 00 1d 20 2f e5 |.....l...h... /.| 37 | 00000190 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff |}.G.bC.(.._.).0.| 38 | 000001a0 f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 08 07 |........._X.;t..| 39 | 000001b0 00 40 a2 12 66 be 81 b1 24 93 f2 e1 60 9f c4 13 |.@..f...$...`...| 40 | 000001c0 04 3f 39 77 8f fe e4 33 5b f7 9d 84 f5 0f 96 aa |.?9w...3[.......| 41 | 000001d0 a0 d6 9d da ae b2 eb 76 64 02 82 58 d4 bc 5a 44 |.......vd..X..ZD| 42 | 000001e0 b9 5a f5 33 57 fa a6 9c d5 05 84 9a 19 0b 65 37 |.Z.3W.........e7| 43 | 000001f0 bc 05 16 03 03 00 04 0e 00 00 00 |...........| 44 | >>> Flow 3 (client to server) 45 | 00000000 16 03 03 00 25 10 00 00 21 20 95 58 05 04 03 27 |....%...! .X...'| 46 | 00000010 5e 14 d4 41 5a 3b eb d3 13 ad d4 16 fb 43 bf d6 |^..AZ;.......C..| 47 | 00000020 7c 0a 1e a9 6c f9 72 84 47 1a 14 03 03 00 01 01 ||...l.r.G.......| 48 | 00000030 16 03 03 00 20 06 f8 af f4 38 35 de 88 74 d6 cc |.... ....85..t..| 49 | 00000040 a8 fa 2c ee a4 88 42 5c 4a aa 62 49 dc 32 da 15 |..,...B\J.bI.2..| 50 | 00000050 1d 9c 5a b8 59 |..Z.Y| 51 | >>> Flow 4 (server to client) 52 | 00000000 14 03 03 00 01 01 16 03 03 00 20 3a 16 00 b6 c5 |.......... :....| 53 | 00000010 76 1f 39 6b 17 2d 2f 34 83 c2 fd 1b 57 c4 0c 02 |v.9k.-/4....W...| 54 | 00000020 18 16 6c d2 92 69 63 9b 32 33 e0 17 03 03 00 1d |..l..ic.23......| 55 | 00000030 04 97 df f0 2c 4b 3d 69 99 36 eb 0b 11 56 97 ab |....,K=i.6...V..| 56 | 00000040 98 5d d9 d4 6f 93 92 5c cc f6 7e 77 40 15 03 03 |.]..o..\..~w@...| 57 | 00000050 00 12 58 cf 6e 90 04 6b ae 4f cf 6b 71 15 80 22 |..X.n..k.O.kq.."| 58 | 00000060 f5 80 fa df |....| 59 | -------------------------------------------------------------------------------- /testdata/Server-TLSv12-Resume: -------------------------------------------------------------------------------- 1 | >>> Flow 1 (client to server) 2 | 00000000 16 03 01 01 0a 01 00 01 06 03 03 2d b6 ca ea 39 |...........-...9| 3 | 00000010 59 17 86 df 90 2f 73 e0 a0 5c 6e 28 09 78 69 d6 |Y..../s..\n(.xi.| 4 | 00000020 30 06 b7 7b 17 a9 79 30 2a d8 57 20 c5 5c ed 86 |0..{..y0*.W .\..| 5 | 00000030 15 f4 3b c8 d2 5f 7a 80 2a 6a cd 40 c2 da 6f a8 |..;.._z.*j.@..o.| 6 | 00000040 cd d7 e7 bf 48 bd fb a1 e9 4b 9b a9 00 04 00 2f |....H....K...../| 7 | 00000050 00 ff 01 00 00 b9 00 23 00 79 00 00 00 00 00 00 |.......#.y......| 8 | 00000060 00 00 00 00 00 00 00 00 00 00 94 6f 2d b0 ac 51 |...........o-..Q| 9 | 00000070 ed 14 ef 68 ca 42 c5 4c 85 f6 26 0d a4 ad a8 f5 |...h.B.L..&.....| 10 | 00000080 14 64 4f b9 c3 fb 1e 55 c1 1f c7 31 57 72 68 db |.dO....U...1Wrh.| 11 | 00000090 03 37 a8 c9 07 f4 ca 62 6c 5c f3 8b 5a 3d 76 dd |.7.....bl\..Z=v.| 12 | 000000a0 63 ea 68 61 6b a1 2d 95 49 38 16 7e 51 5c e5 15 |c.hak.-.I8.~Q\..| 13 | 000000b0 c0 58 7d c5 67 4a 6f 64 b6 79 1a 41 9b b1 33 15 |.X}.gJod.y.A..3.| 14 | 000000c0 38 74 92 5c a5 48 c3 f2 94 bb 33 ec af cf d7 e7 |8t.\.H....3.....| 15 | 000000d0 c9 3e 35 00 16 00 00 00 17 00 00 00 0d 00 30 00 |.>5...........0.| 16 | 000000e0 2e 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 |................| 17 | 000000f0 0b 08 04 08 05 08 06 04 01 05 01 06 01 03 03 02 |................| 18 | 00000100 03 03 01 02 01 03 02 02 02 04 02 05 02 06 02 |...............| 19 | >>> Flow 2 (server to client) 20 | 00000000 16 03 03 00 59 02 00 00 55 03 03 00 00 00 00 00 |....Y...U.......| 21 | 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 22 | 00000020 00 00 00 44 4f 57 4e 47 52 44 01 20 c5 5c ed 86 |...DOWNGRD. .\..| 23 | 00000030 15 f4 3b c8 d2 5f 7a 80 2a 6a cd 40 c2 da 6f a8 |..;.._z.*j.@..o.| 24 | 00000040 cd d7 e7 bf 48 bd fb a1 e9 4b 9b a9 00 2f 00 00 |....H....K.../..| 25 | 00000050 0d 00 23 00 00 ff 01 00 01 00 00 17 00 00 16 03 |..#.............| 26 | 00000060 03 00 83 04 00 00 7f 00 00 00 00 00 79 00 00 00 |............y...| 27 | 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 94 6f 2d |..............o-| 28 | 00000080 b0 ac 51 ed 14 ef 68 ca 42 c5 4c 85 f6 26 0d a4 |..Q...h.B.L..&..| 29 | 00000090 ad a8 f5 14 64 4f b9 c3 fb 1e 55 c1 1f c7 31 57 |....dO....U...1W| 30 | 000000a0 72 68 db 03 37 a8 c9 07 f4 ca 62 6c 5c f3 8b 5a |rh..7.....bl\..Z| 31 | 000000b0 3d 76 dd 63 ea 68 61 6b a1 2d 95 49 38 16 7e 51 |=v.c.hak.-.I8.~Q| 32 | 000000c0 5c e5 15 c0 58 7d c5 67 4a 6f 64 b6 79 1a 41 9b |\...X}.gJod.y.A.| 33 | 000000d0 b1 33 15 38 74 92 5c a5 48 c3 f2 94 bb 33 ec af |.3.8t.\.H....3..| 34 | 000000e0 cf d7 e7 c9 3e 35 14 03 03 00 01 01 16 03 03 00 |....>5..........| 35 | 000000f0 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |@...............| 36 | 00000100 00 47 68 3a 66 5b d6 ed b7 60 a9 fb e8 37 d6 9d |.Gh:f[...`...7..| 37 | 00000110 a6 b9 4d d5 f3 9f 0f c6 3c 21 6e d5 80 08 a8 34 |..M.......k| 39 | 00000130 40 |@| 40 | >>> Flow 3 (client to server) 41 | 00000000 14 03 03 00 01 01 16 03 03 00 40 46 34 b3 97 54 |..........@F4..T| 42 | 00000010 20 5b 95 f3 22 f8 a1 89 c8 95 93 ba 7b a4 a8 8f | [..".......{...| 43 | 00000020 46 a8 d6 c1 b3 ac f0 e0 49 3d 8d e4 1c ac b8 a4 |F.......I=......| 44 | 00000030 01 21 5e d8 f0 f5 10 10 f7 de 8b 33 9d 94 cf f6 |.!^........3....| 45 | 00000040 f2 9b 39 22 5c e6 c0 5e b4 1d cd |..9"\..^...| 46 | >>> Flow 4 (server to client) 47 | 00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| 48 | 00000010 00 00 00 00 00 5c bc 45 06 2e d3 7b 30 99 a6 af |.....\.E...{0...| 49 | 00000020 64 0e 63 93 73 6f 0a e7 a4 1d ac 94 25 11 a5 63 |d.c.so......%..c| 50 | 00000030 8d b2 44 aa 98 44 f8 b5 51 ea 2c fb 26 99 f6 a4 |..D..D..Q.,.&...| 51 | 00000040 2c f8 15 c3 90 15 03 03 00 30 00 00 00 00 00 00 |,........0......| 52 | 00000050 00 00 00 00 00 00 00 00 00 00 c6 58 8e 7c 97 de |...........X.|..| 53 | 00000060 3b b8 39 cd 7b 1d 67 77 27 da 93 39 52 a7 81 9b |;.9.{.gw'..9R...| 54 | 00000070 ab 5a bc e9 00 1a 64 3a ca f5 |.Z....d:..| 55 | -------------------------------------------------------------------------------- /testdata/Server-TLSv13-ALPN-NoMatch: -------------------------------------------------------------------------------- 1 | >>> Flow 1 (client to server) 2 | 00000000 16 03 01 00 e2 01 00 00 de 03 03 3d ae 42 d4 d3 |...........=.B..| 3 | 00000010 a9 75 5b a6 8f 9f 47 6f fe e7 3d 3e 5c d8 35 01 |.u[...Go..=>\.5.| 4 | 00000020 c9 25 fd 94 e4 ac 7e b4 e1 4e 0f 20 56 29 44 cd |.%....~..N. V)D.| 5 | 00000030 7f 99 7b a6 9a 4d d4 3c e8 01 00 93 e5 e0 a8 7b |..{..M.<.......{| 6 | 00000040 81 13 85 e9 2e 4e 12 a2 b9 d4 7d 8e 00 04 13 03 |.....N....}.....| 7 | 00000050 00 ff 01 00 00 91 00 0b 00 04 03 00 01 02 00 0a |................| 8 | 00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| 9 | 00000070 00 00 00 10 00 10 00 0e 06 70 72 6f 74 6f 32 06 |.........proto2.| 10 | 00000080 70 72 6f 74 6f 31 00 16 00 00 00 17 00 00 00 0d |proto1..........| 11 | 00000090 00 1e 00 1c 04 03 05 03 06 03 08 07 08 08 08 09 |................| 12 | 000000a0 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| 13 | 000000b0 00 2b 00 03 02 03 04 00 2d 00 02 01 01 00 33 00 |.+......-.....3.| 14 | 000000c0 26 00 24 00 1d 00 20 3c 8b f2 09 ad ff 96 76 0f |&.$... <......v.| 15 | 000000d0 9b 05 eb c8 5a 48 68 be a6 6e dd f6 f5 7d 56 89 |....ZHh..n...}V.| 16 | 000000e0 ff 37 75 13 b1 1b 01 |.7u....| 17 | >>> Flow 2 (server to client) 18 | 00000000 15 03 03 00 02 02 78 |......x| 19 | -------------------------------------------------------------------------------- /testdata/Server-TLSv13-RSA-RSAPSS-TooSmall: -------------------------------------------------------------------------------- 1 | >>> Flow 1 (client to server) 2 | 00000000 16 03 01 00 b0 01 00 00 ac 03 03 15 df ef fb ff |................| 3 | 00000010 00 89 4d bf 59 d2 30 f1 f3 e7 20 24 c6 06 ba a4 |..M.Y.0... $....| 4 | 00000020 28 b4 ba 3d 00 f2 18 9b 98 a3 f2 20 7e d9 d0 58 |(..=....... ~..X| 5 | 00000030 50 25 90 2d f0 af 72 66 fb f8 54 33 6e d4 2b f0 |P%.-..rf..T3n.+.| 6 | 00000040 0f 1a ea dc 9e 08 34 ed 68 a8 d8 bd 00 04 13 03 |......4.h.......| 7 | 00000050 00 ff 01 00 00 5f 00 0b 00 04 03 00 01 02 00 0a |....._..........| 8 | 00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 16 |................| 9 | 00000070 00 00 00 17 00 00 00 0d 00 04 00 02 08 06 00 2b |...............+| 10 | 00000080 00 03 02 03 04 00 2d 00 02 01 01 00 33 00 26 00 |......-.....3.&.| 11 | 00000090 24 00 1d 00 20 6e 42 98 d4 04 32 d1 21 0f 64 c9 |$... nB...2.!.d.| 12 | 000000a0 b7 f2 b2 52 6f 2b b7 b1 95 4b 57 85 7b 69 d9 63 |...Ro+...KW.{i.c| 13 | 000000b0 19 48 d2 1c 1e |.H...| 14 | >>> Flow 2 (server to client) 15 | 00000000 15 03 03 00 02 02 28 |......(| 16 | -------------------------------------------------------------------------------- /testdata/Server-TLSv13-Resume: -------------------------------------------------------------------------------- 1 | >>> Flow 1 (client to server) 2 | 00000000 16 03 01 01 66 01 00 01 62 03 03 45 a3 e1 2e f2 |....f...b..E....| 3 | 00000010 03 d1 82 45 cb cd fc da ae 9d 47 ce 2b fd 5a df |...E......G.+.Z.| 4 | 00000020 ad dd 7b 1a 4a 14 93 bb d1 fe f5 20 78 6c c9 94 |..{.J...... xl..| 5 | 00000030 6a b6 3e 65 97 42 9f c3 80 3c 8a 23 f5 af 6d 4b |j.>e.B...<.#..mK| 6 | 00000040 cb dc e9 93 22 bd bf b5 e6 09 0d e1 00 04 13 01 |...."...........| 7 | 00000050 00 ff 01 00 01 15 00 0b 00 04 03 00 01 02 00 0a |................| 8 | 00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| 9 | 00000070 00 00 00 16 00 00 00 17 00 00 00 0d 00 1e 00 1c |................| 10 | 00000080 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b |................| 11 | 00000090 08 04 08 05 08 06 04 01 05 01 06 01 00 2b 00 03 |.............+..| 12 | 000000a0 02 03 04 00 2d 00 02 01 01 00 33 00 26 00 24 00 |....-.....3.&.$.| 13 | 000000b0 1d 00 20 49 31 09 86 3b 71 6b ff 6c bc 6f 40 4c |.. I1..;qk.l.o@L| 14 | 000000c0 3a 04 44 c3 83 6c 9b 1d 99 a6 10 c7 07 f9 9d 57 |:.D..l.........W| 15 | 000000d0 2d b4 59 00 29 00 94 00 6f 00 69 00 00 00 00 00 |-.Y.)...o.i.....| 16 | 000000e0 00 00 00 00 00 00 00 00 00 00 00 94 68 2d a3 82 |............h-..| 17 | 000000f0 51 ed 14 ef 68 ca 42 c5 5c 95 7a 77 9a 7a 61 99 |Q...h.B.\.zw.za.| 18 | 00000100 c6 44 1e e6 5d 71 41 c8 77 d1 d4 b6 39 bb 38 57 |.D..]qA.w...9.8W| 19 | 00000110 41 b8 41 f2 02 96 d0 b0 5b 99 76 3c 2b 52 f2 8f |A.A.....[.v<+R..| 20 | 00000120 5f 33 94 fa 66 74 cc f0 60 1b ee 0a 38 30 78 b2 |_3..ft..`...80x.| 21 | 00000130 9e 54 16 d6 71 0e b2 ea 4e 0f 13 f0 6e 63 88 e7 |.T..q...N...nc..| 22 | 00000140 9f 55 65 0b 00 00 00 00 00 21 20 21 c5 95 b2 62 |.Ue......! !...b| 23 | 00000150 61 dc b6 32 34 60 19 58 8c 6b 4b de dc 39 c7 d6 |a..24`.X.kK..9..| 24 | 00000160 82 55 c8 de 80 dc b7 05 0c be a6 |.U.........| 25 | >>> Flow 2 (server to client) 26 | 00000000 16 03 03 00 80 02 00 00 7c 03 03 00 00 00 00 00 |........|.......| 27 | 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 28 | 00000020 00 00 00 00 00 00 00 00 00 00 00 20 78 6c c9 94 |........... xl..| 29 | 00000030 6a b6 3e 65 97 42 9f c3 80 3c 8a 23 f5 af 6d 4b |j.>e.B...<.#..mK| 30 | 00000040 cb dc e9 93 22 bd bf b5 e6 09 0d e1 13 01 00 00 |...."...........| 31 | 00000050 34 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |4.+.....3.$... /| 32 | 00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 33 | 00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 00 |.........._X.;t.| 34 | 00000080 29 00 02 00 00 14 03 03 00 01 01 17 03 03 00 17 |)...............| 35 | 00000090 b4 11 54 4d 78 28 66 53 0f fd c8 7c d5 1c 1d b2 |..TMx(fS...|....| 36 | 000000a0 06 31 23 27 a4 70 b2 17 03 03 00 35 86 87 b6 21 |.1#'.p.....5...!| 37 | 000000b0 1c db f6 8c 4f ae 46 26 27 23 5d 1f 41 1d 42 94 |....O.F&'#].A.B.| 38 | 000000c0 68 32 e5 49 19 e9 bc ba 4e 0a e2 71 7e 31 d2 a0 |h2.I....N..q~1..| 39 | 000000d0 c2 24 b3 a9 3d 26 a5 eb c9 44 09 03 7a 14 54 5d |.$..=&...D..z.T]| 40 | 000000e0 8f 17 03 03 00 8b fd cd ed ac c5 f2 7c 99 66 85 |............|.f.| 41 | 000000f0 e6 0c 3b 9d ca a2 fb 22 69 fc 40 61 3a 98 f2 db |..;...."i.@a:...| 42 | 00000100 84 7b d9 70 06 7f 00 20 53 cb ce 27 f1 93 fd 01 |.{.p... S..'....| 43 | 00000110 fb 0d 32 61 0d 04 93 d3 53 94 a4 37 ed a6 6e 5c |..2a....S..7..n\| 44 | 00000120 2f 9a 9a a9 1b b2 26 1d 24 9f 78 05 53 1d aa 40 |/.....&.$.x.S..@| 45 | 00000130 bb 3f 27 29 ac 56 97 d7 f8 a8 77 e9 d4 b3 c0 43 |.?').V....w....C| 46 | 00000140 a8 27 12 0f 13 fd 62 27 01 54 90 b5 66 fd d8 41 |.'....b'.T..f..A| 47 | 00000150 a0 3a 5f b5 eb 53 25 83 f0 35 65 b2 7b f7 c6 a1 |.:_..S%..5e.{...| 48 | 00000160 47 20 c5 91 00 69 b4 28 32 3c 55 8d 34 b9 ab b7 |G ...i.(2>> Flow 3 (client to server) 51 | 00000000 14 03 03 00 01 01 17 03 03 00 35 fb 04 e7 9f ad |..........5.....| 52 | 00000010 51 52 7e 72 61 46 df d0 80 5b 1a f3 ce 78 9e ae |QR~raF...[...x..| 53 | 00000020 f8 cb 08 7e 2b 45 e9 f6 20 10 e0 99 4f 1a 62 51 |...~+E.. ...O.bQ| 54 | 00000030 4f b6 d4 2a 5e b8 04 2b 09 06 4a 03 c4 01 ca bf |O..*^..+..J.....| 55 | >>> Flow 4 (server to client) 56 | 00000000 17 03 03 00 1e 5c c3 b1 a5 d9 f3 a7 0b 48 b6 1f |.....\.......H..| 57 | 00000010 73 ca d2 f5 07 6c e5 37 e9 b0 5f 87 a4 59 0d da |s....l.7.._..Y..| 58 | 00000020 e2 3f ee 17 03 03 00 13 06 d0 6c 12 91 3c 0d cf |.?........l..<..| 59 | 00000030 d2 0f 7f 74 e6 26 79 87 cf 76 71 |...t.&y..vq| 60 | -------------------------------------------------------------------------------- /testdata/example-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw 3 | DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow 4 | EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d 5 | 7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B 6 | 5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr 7 | BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1 8 | NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l 9 | Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc 10 | 6MF9+Yw1Yy0t 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /testdata/example-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49 3 | AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q 4 | EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /testenv/testenv_cgo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. 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 | //go:build cgo 6 | // +build cgo 7 | 8 | package testenv 9 | 10 | func init() { 11 | haveCGO = true 12 | } 13 | -------------------------------------------------------------------------------- /testenv/testenv_notunix.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. 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 | //go:build windows || plan9 || (js && wasm) 6 | // +build windows plan9 js,wasm 7 | 8 | package testenv 9 | 10 | import "os" 11 | 12 | // Sigquit is the signal to send to kill a hanging subprocess. 13 | // On Unix we send SIGQUIT, but on non-Unix we only have os.Kill. 14 | var Sigquit = os.Kill 15 | -------------------------------------------------------------------------------- /testenv/testenv_notwin.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. 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 | //go:build !windows 6 | // +build !windows 7 | 8 | package testenv 9 | 10 | import ( 11 | "runtime" 12 | ) 13 | 14 | func hasSymlink() (ok bool, reason string) { 15 | switch runtime.GOOS { 16 | case "android", "plan9": 17 | return false, "" 18 | } 19 | 20 | return true, "" 21 | } 22 | -------------------------------------------------------------------------------- /testenv/testenv_unix.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. 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 | //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris 6 | // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris 7 | 8 | package testenv 9 | 10 | import "syscall" 11 | 12 | // Sigquit is the signal to send to kill a hanging subprocess. 13 | // Send SIGQUIT to get a stack trace. 14 | var Sigquit = syscall.SIGQUIT 15 | -------------------------------------------------------------------------------- /testenv/testenv_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. 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 testenv 6 | 7 | import ( 8 | "os" 9 | "path/filepath" 10 | "sync" 11 | "syscall" 12 | ) 13 | 14 | var symlinkOnce sync.Once 15 | var winSymlinkErr error 16 | 17 | func initWinHasSymlink() { 18 | tmpdir, err := os.MkdirTemp("", "symtest") 19 | if err != nil { 20 | panic("failed to create temp directory: " + err.Error()) 21 | } 22 | defer os.RemoveAll(tmpdir) 23 | 24 | err = os.Symlink("target", filepath.Join(tmpdir, "symlink")) 25 | if err != nil { 26 | err = err.(*os.LinkError).Err 27 | switch err { 28 | case syscall.EWINDOWS, syscall.ERROR_PRIVILEGE_NOT_HELD: 29 | winSymlinkErr = err 30 | } 31 | } 32 | } 33 | 34 | func hasSymlink() (ok bool, reason string) { 35 | symlinkOnce.Do(initWinHasSymlink) 36 | 37 | switch winSymlinkErr { 38 | case nil: 39 | return true, "" 40 | case syscall.EWINDOWS: 41 | return false, ": symlinks are not supported on your version of Windows" 42 | case syscall.ERROR_PRIVILEGE_NOT_HELD: 43 | return false, ": you don't have enough privileges to create symlinks" 44 | } 45 | 46 | return false, "" 47 | } 48 | -------------------------------------------------------------------------------- /ticket_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. 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 | var _ = &Config{WrapSession: (&Config{}).EncryptTicket} 8 | var _ = &Config{UnwrapSession: (&Config{}).DecryptTicket} 9 | -------------------------------------------------------------------------------- /tls_cf.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Cloudflare, Inc. All rights reserved. Use of this source code 2 | // is governed by a BSD-style license that can be found in the LICENSE file. 3 | 4 | package tls 5 | 6 | import ( 7 | circlPki "github.com/cloudflare/circl/pki" 8 | circlSign "github.com/cloudflare/circl/sign" 9 | "github.com/cloudflare/circl/sign/eddilithium3" 10 | ) 11 | 12 | // To add a signature scheme from Circl 13 | // 14 | // 1. make sure it implements TLSScheme and CertificateScheme, 15 | // 2. follow the instructions in crypto/x509/x509_cf.go 16 | // 3. add a signature to the iota in common.go 17 | // 4. add row in the circlSchemes lists below 18 | 19 | var circlSchemes = [...]struct { 20 | sigType uint8 21 | scheme circlSign.Scheme 22 | }{ 23 | {signatureEdDilithium3, eddilithium3.Scheme()}, 24 | } 25 | 26 | func circlSchemeBySigType(sigType uint8) circlSign.Scheme { 27 | for _, cs := range circlSchemes { 28 | if cs.sigType == sigType { 29 | return cs.scheme 30 | } 31 | } 32 | return nil 33 | } 34 | 35 | func sigTypeByCirclScheme(scheme circlSign.Scheme) uint8 { 36 | for _, cs := range circlSchemes { 37 | if cs.scheme == scheme { 38 | return cs.sigType 39 | } 40 | } 41 | return 0 42 | } 43 | 44 | var supportedSignatureAlgorithmsWithCircl []SignatureScheme 45 | 46 | // supportedSignatureAlgorithms returns enabled signature schemes. PQ signature 47 | // schemes are only included when tls.Config#PQSignatureSchemesEnabled is set 48 | // and FIPS-only mode is not enabled. 49 | func (c *Config) supportedSignatureAlgorithms() []SignatureScheme { 50 | if c != nil && c.PQSignatureSchemesEnabled { 51 | return supportedSignatureAlgorithmsWithCircl 52 | } 53 | return defaultSupportedSignatureAlgorithms 54 | } 55 | 56 | func init() { 57 | supportedSignatureAlgorithmsWithCircl = append([]SignatureScheme{}, defaultSupportedSignatureAlgorithms...) 58 | for _, cs := range circlSchemes { 59 | supportedSignatureAlgorithmsWithCircl = append(supportedSignatureAlgorithmsWithCircl, 60 | SignatureScheme(cs.scheme.(circlPki.TLSScheme).TLSIdentifier())) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /u_alias.go: -------------------------------------------------------------------------------- 1 | package tls 2 | 3 | import ( 4 | "crypto/ecdh" 5 | 6 | "github.com/cloudflare/circl/kem" 7 | ) 8 | 9 | // This file contains all the alias functions, symbols, names, etc. that 10 | // was once used in the old version of the library. This is to ensure 11 | // backwards compatibility with the old version of the library. 12 | 13 | // TLS Extensions 14 | 15 | // UtlsExtendedMasterSecretExtension is an alias for ExtendedMasterSecretExtension. 16 | // 17 | // Deprecated: Use ExtendedMasterSecretExtension instead. 18 | type UtlsExtendedMasterSecretExtension = ExtendedMasterSecretExtension 19 | 20 | // Deprecated: Use KeySharePrivateKeys instead. This type is not used and will be removed in the future. 21 | // KeySharesParameters serves as a in-memory storage for generated keypairs by UTLS when generating 22 | // ClientHello. It is used to store both ecdhe and kem keypairs. 23 | type KeySharesParameters struct{} 24 | 25 | func NewKeySharesParameters() *KeySharesParameters { return &KeySharesParameters{} } 26 | 27 | func (*KeySharesParameters) AddEcdheKeypair(curveID CurveID, ecdheKey *ecdh.PrivateKey, ecdhePubKey *ecdh.PublicKey) { 28 | return 29 | } 30 | 31 | func (*KeySharesParameters) GetEcdheKey(curveID CurveID) (ecdheKey *ecdh.PrivateKey, ok bool) { return } 32 | 33 | func (*KeySharesParameters) GetEcdhePubkey(curveID CurveID) (params *ecdh.PublicKey, ok bool) { return } 34 | 35 | func (*KeySharesParameters) AddKemKeypair(curveID CurveID, kemKey kem.PrivateKey, kemPubKey kem.PublicKey) { 36 | return 37 | } 38 | 39 | func (ksp *KeySharesParameters) GetKemKey(curveID CurveID) (kemKey kem.PrivateKey, ok bool) { return } 40 | 41 | func (ksp *KeySharesParameters) GetKemPubkey(curveID CurveID) (params kem.PublicKey, ok bool) { return } 42 | -------------------------------------------------------------------------------- /u_clienthello_json_test.go: -------------------------------------------------------------------------------- 1 | package tls 2 | 3 | import ( 4 | "encoding/json" 5 | "os" 6 | "reflect" 7 | "testing" 8 | ) 9 | 10 | func TestClientHelloSpecJSONUnmarshaler(t *testing.T) { 11 | testClientHelloSpecJSONUnmarshaler(t, "testdata/ClientHello-JSON-Chrome102.json", HelloChrome_102) 12 | testClientHelloSpecJSONUnmarshaler(t, "testdata/ClientHello-JSON-Firefox105.json", HelloFirefox_105) 13 | testClientHelloSpecJSONUnmarshaler(t, "testdata/ClientHello-JSON-iOS14.json", HelloIOS_14) 14 | testClientHelloSpecJSONUnmarshaler(t, "testdata/ClientHello-JSON-Edge106.json", HelloEdge_106) 15 | } 16 | 17 | func testClientHelloSpecJSONUnmarshaler( 18 | t *testing.T, 19 | jsonFilepath string, 20 | truthClientHelloID ClientHelloID, 21 | ) { 22 | jsonCH, err := os.ReadFile(jsonFilepath) 23 | if err != nil { 24 | t.Fatal(err) 25 | } 26 | 27 | var chsju ClientHelloSpecJSONUnmarshaler 28 | if err := json.Unmarshal(jsonCH, &chsju); err != nil { 29 | t.Fatal(err) 30 | } 31 | 32 | truthSpec, _ := utlsIdToSpec(truthClientHelloID) 33 | jsonSpec := chsju.ClientHelloSpec() 34 | 35 | // Compare CipherSuites 36 | if !reflect.DeepEqual(jsonSpec.CipherSuites, truthSpec.CipherSuites) { 37 | t.Errorf("JSONUnmarshaler %s: got %#v, want %#v", clientHelloSpecJSONTestIdentifier(truthClientHelloID), jsonSpec.CipherSuites, truthSpec.CipherSuites) 38 | } 39 | 40 | // Compare CompressionMethods 41 | if !reflect.DeepEqual(jsonSpec.CompressionMethods, truthSpec.CompressionMethods) { 42 | t.Errorf("JSONUnmarshaler %s: got %#v, want %#v", clientHelloSpecJSONTestIdentifier(truthClientHelloID), jsonSpec.CompressionMethods, truthSpec.CompressionMethods) 43 | } 44 | 45 | // Compare Extensions 46 | if len(jsonSpec.Extensions) != len(truthSpec.Extensions) { 47 | t.Errorf("JSONUnmarshaler %s: len(jsonExtensions) = %d != %d = len(truthExtensions)", clientHelloSpecJSONTestIdentifier(truthClientHelloID), len(jsonSpec.Extensions), len(truthSpec.Extensions)) 48 | } 49 | 50 | for i := range jsonSpec.Extensions { 51 | if !reflect.DeepEqual(jsonSpec.Extensions[i], truthSpec.Extensions[i]) { 52 | if _, ok := jsonSpec.Extensions[i].(*UtlsPaddingExtension); ok { 53 | testedPaddingExt := jsonSpec.Extensions[i].(*UtlsPaddingExtension) 54 | savedPaddingExt := truthSpec.Extensions[i].(*UtlsPaddingExtension) 55 | if testedPaddingExt.PaddingLen != savedPaddingExt.PaddingLen || testedPaddingExt.WillPad != savedPaddingExt.WillPad { 56 | t.Errorf("got %#v, want %#v", testedPaddingExt, savedPaddingExt) 57 | } else { 58 | continue // UtlsPaddingExtension has non-nil function member 59 | } 60 | } 61 | t.Errorf("JSONUnmarshaler %s: got %#v, want %#v", clientHelloSpecJSONTestIdentifier(truthClientHelloID), jsonSpec.Extensions[i], truthSpec.Extensions[i]) 62 | } 63 | } 64 | } 65 | 66 | func TestClientHelloSpecUnmarshalJSON(t *testing.T) { 67 | testClientHelloSpecUnmarshalJSON(t, "testdata/ClientHello-JSON-Chrome102.json", HelloChrome_102) 68 | testClientHelloSpecUnmarshalJSON(t, "testdata/ClientHello-JSON-Firefox105.json", HelloFirefox_105) 69 | testClientHelloSpecUnmarshalJSON(t, "testdata/ClientHello-JSON-iOS14.json", HelloIOS_14) 70 | testClientHelloSpecUnmarshalJSON(t, "testdata/ClientHello-JSON-Edge106.json", HelloEdge_106) 71 | } 72 | 73 | func testClientHelloSpecUnmarshalJSON( 74 | t *testing.T, 75 | jsonFilepath string, 76 | truthClientHelloID ClientHelloID, 77 | ) { 78 | var jsonSpec ClientHelloSpec 79 | jsonCH, err := os.ReadFile(jsonFilepath) 80 | if err != nil { 81 | t.Fatal(err) 82 | } 83 | 84 | if err := json.Unmarshal(jsonCH, &jsonSpec); err != nil { 85 | t.Fatal(err) 86 | } 87 | 88 | truthSpec, _ := utlsIdToSpec(truthClientHelloID) 89 | 90 | // Compare CipherSuites 91 | if !reflect.DeepEqual(jsonSpec.CipherSuites, truthSpec.CipherSuites) { 92 | t.Errorf("UnmarshalJSON %s: got %#v, want %#v", clientHelloSpecJSONTestIdentifier(truthClientHelloID), jsonSpec.CipherSuites, truthSpec.CipherSuites) 93 | } 94 | 95 | // Compare CompressionMethods 96 | if !reflect.DeepEqual(jsonSpec.CompressionMethods, truthSpec.CompressionMethods) { 97 | t.Errorf("UnmarshalJSON %s: got %#v, want %#v", clientHelloSpecJSONTestIdentifier(truthClientHelloID), jsonSpec.CompressionMethods, truthSpec.CompressionMethods) 98 | } 99 | 100 | // Compare Extensions 101 | if len(jsonSpec.Extensions) != len(truthSpec.Extensions) { 102 | t.Errorf("UnmarshalJSON %s: len(jsonExtensions) = %d != %d = len(truthExtensions)", jsonFilepath, len(jsonSpec.Extensions), len(truthSpec.Extensions)) 103 | } 104 | 105 | for i := range jsonSpec.Extensions { 106 | if !reflect.DeepEqual(jsonSpec.Extensions[i], truthSpec.Extensions[i]) { 107 | if _, ok := jsonSpec.Extensions[i].(*UtlsPaddingExtension); ok { 108 | testedPaddingExt := jsonSpec.Extensions[i].(*UtlsPaddingExtension) 109 | savedPaddingExt := truthSpec.Extensions[i].(*UtlsPaddingExtension) 110 | if testedPaddingExt.PaddingLen != savedPaddingExt.PaddingLen || testedPaddingExt.WillPad != savedPaddingExt.WillPad { 111 | t.Errorf("got %#v, want %#v", testedPaddingExt, savedPaddingExt) 112 | } else { 113 | continue // UtlsPaddingExtension has non-nil function member 114 | } 115 | } 116 | t.Errorf("UnmarshalJSON %s: got %#v, want %#v", clientHelloSpecJSONTestIdentifier(truthClientHelloID), jsonSpec.Extensions[i], truthSpec.Extensions[i]) 117 | } 118 | } 119 | } 120 | 121 | func clientHelloSpecJSONTestIdentifier(id ClientHelloID) string { 122 | return id.Client + id.Version 123 | } 124 | -------------------------------------------------------------------------------- /u_common_test.go: -------------------------------------------------------------------------------- 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 | "testing" 9 | ) 10 | 11 | func TestUTLSIsGrease(t *testing.T) { 12 | 13 | var testMap = []struct { 14 | version uint16 15 | isGREASE bool 16 | }{ 17 | {0x0a0a, true}, 18 | {0x1a1a, true}, 19 | {0x2a1a, false}, 20 | {0x2a2a, true}, 21 | {0x1234, false}, 22 | {0x1a2a, false}, 23 | {0xdeed, false}, 24 | {0xb1b1, false}, 25 | {0x0b0b, false}, 26 | } 27 | 28 | for _, testCase := range testMap { 29 | if isGREASEUint16(testCase.version) != testCase.isGREASE { 30 | t.Errorf("misidentified GREASE: testing %x, isGREASE: %v", testCase.version, isGREASEUint16(testCase.version)) 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /u_ech_config.go: -------------------------------------------------------------------------------- 1 | package tls 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | "github.com/cloudflare/circl/hpke" 8 | "golang.org/x/crypto/cryptobyte" 9 | ) 10 | 11 | type ECHConfigContents struct { 12 | KeyConfig HPKEKeyConfig 13 | MaximumNameLength uint8 14 | PublicName []byte 15 | // Extensions []TLSExtension // ignored for now 16 | rawExtensions []byte 17 | } 18 | 19 | func UnmarshalECHConfigContents(contents []byte) (ECHConfigContents, error) { 20 | var ( 21 | contentCryptobyte = cryptobyte.String(contents) 22 | config ECHConfigContents 23 | ) 24 | 25 | // Parse KeyConfig 26 | var t cryptobyte.String 27 | if !contentCryptobyte.ReadUint8(&config.KeyConfig.ConfigId) || 28 | !contentCryptobyte.ReadUint16(&config.KeyConfig.KemId) || 29 | !contentCryptobyte.ReadUint16LengthPrefixed(&t) || 30 | !t.ReadBytes(&config.KeyConfig.rawPublicKey, len(t)) || 31 | !contentCryptobyte.ReadUint16LengthPrefixed(&t) || 32 | len(t)%4 != 0 { 33 | return config, errors.New("error parsing KeyConfig") 34 | } 35 | 36 | // Parse all CipherSuites in KeyConfig 37 | config.KeyConfig.CipherSuites = nil 38 | for !t.Empty() { 39 | var kdfId, aeadId uint16 40 | if !t.ReadUint16(&kdfId) || !t.ReadUint16(&aeadId) { 41 | // This indicates an internal bug. 42 | panic("internal error while parsing contents.cipher_suites") 43 | } 44 | config.KeyConfig.CipherSuites = append(config.KeyConfig.CipherSuites, HPKESymmetricCipherSuite{kdfId, aeadId}) 45 | } 46 | 47 | if !contentCryptobyte.ReadUint8(&config.MaximumNameLength) || 48 | !contentCryptobyte.ReadUint8LengthPrefixed(&t) || 49 | !t.ReadBytes(&config.PublicName, len(t)) || 50 | !contentCryptobyte.ReadUint16LengthPrefixed(&t) || 51 | !t.ReadBytes(&config.rawExtensions, len(t)) || 52 | !contentCryptobyte.Empty() { 53 | return config, errors.New("error parsing ECHConfigContents") 54 | } 55 | return config, nil 56 | } 57 | 58 | func (echcc *ECHConfigContents) ParsePublicKey() error { 59 | var err error 60 | kem := hpke.KEM(echcc.KeyConfig.KemId) 61 | if !kem.IsValid() { 62 | return errors.New("invalid KEM") 63 | } 64 | echcc.KeyConfig.PublicKey, err = kem.Scheme().UnmarshalBinaryPublicKey(echcc.KeyConfig.rawPublicKey) 65 | if err != nil { 66 | return fmt.Errorf("error parsing public key: %s", err) 67 | } 68 | return nil 69 | } 70 | 71 | type ECHConfig struct { 72 | Version uint16 73 | Length uint16 74 | Contents ECHConfigContents 75 | 76 | raw []byte 77 | } 78 | 79 | // UnmarshalECHConfigs parses a sequence of ECH configurations. 80 | // 81 | // Ported from cloudflare/go 82 | func UnmarshalECHConfigs(raw []byte) ([]ECHConfig, error) { 83 | var ( 84 | err error 85 | config ECHConfig 86 | t, contents cryptobyte.String 87 | ) 88 | configs := make([]ECHConfig, 0) 89 | s := cryptobyte.String(raw) 90 | if !s.ReadUint16LengthPrefixed(&t) || !s.Empty() { 91 | return configs, errors.New("error parsing configs") 92 | } 93 | raw = raw[2:] 94 | ConfigsLoop: 95 | for !t.Empty() { 96 | l := len(t) 97 | if !t.ReadUint16(&config.Version) || 98 | !t.ReadUint16LengthPrefixed(&contents) { 99 | return nil, errors.New("error parsing config") 100 | } 101 | config.Length = uint16(len(contents)) 102 | n := l - len(t) 103 | config.raw = raw[:n] 104 | raw = raw[n:] 105 | 106 | if config.Version != utlsExtensionECH { 107 | continue ConfigsLoop 108 | } 109 | 110 | /**** cloudflare/go original ****/ 111 | // if !readConfigContents(&contents, &config) { 112 | // return nil, errors.New("error parsing config contents") 113 | // } 114 | 115 | config.Contents, err = UnmarshalECHConfigContents(contents) 116 | if err != nil { 117 | return nil, fmt.Errorf("error parsing config contents: %s", err) 118 | } 119 | 120 | /**** cloudflare/go original ****/ 121 | // kem := hpke.KEM(config.kemId) 122 | // if !kem.IsValid() { 123 | // continue ConfigsLoop 124 | // } 125 | // config.pk, err = kem.Scheme().UnmarshalBinaryPublicKey(config.rawPublicKey) 126 | // if err != nil { 127 | // return nil, fmt.Errorf("error parsing public key: %s", err) 128 | // } 129 | 130 | config.Contents.ParsePublicKey() // parse the bytes into a public key 131 | 132 | configs = append(configs, config) 133 | } 134 | return configs, nil 135 | } 136 | -------------------------------------------------------------------------------- /u_ech_test.go: -------------------------------------------------------------------------------- 1 | package tls_test 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | "testing" 7 | 8 | tls "github.com/refraction-networking/utls" 9 | "github.com/refraction-networking/utls/dicttls" 10 | ) 11 | 12 | func TestGREASEECHWrite(t *testing.T) { 13 | for _, testsuite := range []rawECHTestSuite{rawECH_HKDFSHA256_AES128GCM} { 14 | 15 | gech := &tls.GREASEEncryptedClientHelloExtension{} 16 | 17 | n, err := gech.Write(testsuite.raw[4:]) // skip the first 4 bytes which are the extension type and length 18 | if err != nil { 19 | t.Fatalf("Failed to write GREASE ECH extension: %s", err) 20 | } 21 | 22 | if n != len(testsuite.raw[4:]) { 23 | t.Fatalf("Failed to write all GREASE ECH extension bytes: %d != %d", n, len(testsuite.raw[4:])) 24 | } 25 | 26 | var gechBytes []byte = make([]byte, 1024) 27 | n, err = gech.Read(gechBytes) 28 | if err != nil && !errors.Is(err, io.EOF) { 29 | t.Fatalf("Failed to read GREASE ECH extension: %s", err) 30 | } 31 | 32 | if n != len(testsuite.raw) { 33 | t.Fatalf("GREASE ECH Read length mismatch: %d != %d", n, len(testsuite.raw)) 34 | } 35 | 36 | // manually check fields in the GREASE ECH extension 37 | if len(gech.CandidateCipherSuites) != 1 || 38 | gech.CandidateCipherSuites[0].KdfId != testsuite.kdfID || 39 | gech.CandidateCipherSuites[0].AeadId != testsuite.aeadID { 40 | t.Fatalf("GREASE ECH Read cipher suite mismatch") 41 | } 42 | 43 | if len(gech.EncapsulatedKey) != int(testsuite.encapsulatedKeyLength) { 44 | t.Fatalf("GREASE ECH Read encapsulated key length mismatch") 45 | } 46 | 47 | if len(gech.CandidatePayloadLens) != 1 || gech.CandidatePayloadLens[0] != testsuite.payloadLength { 48 | t.Fatalf("GREASE ECH Read payload length mismatch") 49 | } 50 | } 51 | } 52 | 53 | type rawECHTestSuite struct { 54 | kdfID uint16 55 | aeadID uint16 56 | encapsulatedKeyLength uint16 57 | payloadLength uint16 58 | 59 | raw []byte 60 | } 61 | 62 | var ( 63 | rawECH_HKDFSHA256_AES128GCM rawECHTestSuite = rawECHTestSuite{ 64 | kdfID: dicttls.HKDF_SHA256, 65 | aeadID: dicttls.AEAD_AES_128_GCM, 66 | encapsulatedKeyLength: 32, 67 | payloadLength: 208 - 16, 68 | raw: []byte{ 69 | 0xfe, 0x0d, 0x00, 0xfa, 0x00, 0x00, 0x01, 0x00, 70 | 0x01, 0x77, 0x00, 0x20, 0x3d, 0x3e, 0xe0, 0xa6, 71 | 0x1f, 0x46, 0x4f, 0x89, 0x5f, 0x39, 0x4a, 0xfd, 72 | 0x6e, 0xbc, 0x7f, 0x4e, 0xe2, 0x5a, 0xdc, 0x4e, 73 | 0xda, 0x9a, 0x9f, 0x5f, 0x2b, 0xf5, 0x21, 0x0e, 74 | 0xc6, 0x33, 0x64, 0x32, 0x00, 0xd0, 0xae, 0xff, 75 | 0x25, 0xd6, 0x4a, 0x23, 0x3a, 0x13, 0x5b, 0xdc, 76 | 0xe4, 0xaf, 0x6c, 0xb8, 0xaf, 0x66, 0x57, 0xbd, 77 | 0x44, 0x2d, 0xca, 0xb6, 0xbb, 0xaf, 0xda, 0x8a, 78 | 0x6b, 0x12, 0xb2, 0x42, 0xf1, 0x3d, 0xf6, 0x26, 79 | 0xd4, 0x82, 0x30, 0x40, 0xd4, 0x53, 0x06, 0x7c, 80 | 0xf1, 0x10, 0xf3, 0x80, 0x16, 0x95, 0xa7, 0xfb, 81 | 0x08, 0x76, 0x82, 0x85, 0x86, 0xb4, 0x3a, 0x7b, 82 | 0xea, 0xfb, 0xaa, 0xc3, 0xe0, 0x51, 0xcf, 0x42, 83 | 0xf6, 0xa0, 0x15, 0x0e, 0x26, 0x4d, 0x37, 0x35, 84 | 0x95, 0x4d, 0xce, 0xf6, 0xd6, 0x58, 0x78, 0x67, 85 | 0x42, 0xd3, 0xc6, 0xac, 0xb5, 0xe9, 0x3e, 0xb6, 86 | 0x02, 0x87, 0x66, 0xb3, 0xb2, 0x56, 0x99, 0xb2, 87 | 0xdb, 0x8c, 0x3b, 0x04, 0xf1, 0x7c, 0x85, 0x5b, 88 | 0xc3, 0x93, 0x8e, 0xdb, 0x5d, 0x87, 0x66, 0xfb, 89 | 0x66, 0x54, 0xf3, 0xec, 0x25, 0xe5, 0x70, 0x3c, 90 | 0xd5, 0x0e, 0x8e, 0xd5, 0xd2, 0xbb, 0x24, 0x2b, 91 | 0xb5, 0x01, 0xa0, 0x5e, 0xba, 0x45, 0xaf, 0x68, 92 | 0x96, 0x8a, 0x83, 0x90, 0x20, 0x5b, 0x8c, 0x7d, 93 | 0x24, 0x00, 0x2f, 0x08, 0x7f, 0x29, 0x8c, 0x32, 94 | 0x5e, 0x57, 0xb5, 0x64, 0xaa, 0x0b, 0xf4, 0x42, 95 | 0x54, 0xdc, 0xe5, 0xd4, 0x08, 0xf4, 0x4d, 0x27, 96 | 0x5d, 0x90, 0x52, 0x32, 0x22, 0xc8, 0xb6, 0xd8, 97 | 0x80, 0xa6, 0x30, 0xa0, 0x20, 0x98, 0x2c, 0x0b, 98 | 0x3e, 0x55, 0x4a, 0x09, 0xa9, 0x09, 0xa4, 0x99, 99 | 0x89, 0x02, 0x6e, 0xab, 0xe3, 0xa1, 0xe9, 0xb8, 100 | 0x58, 0x20, 0xcc, 0xc8, 0xb0, 0x73, 101 | }, 102 | } 103 | ) 104 | -------------------------------------------------------------------------------- /u_fingerprinter.go: -------------------------------------------------------------------------------- 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 | // Fingerprinter is a struct largely for holding options for the FingerprintClientHello func 8 | type Fingerprinter struct { 9 | // AllowBluntMimicry will ensure that unknown extensions are 10 | // passed along into the resulting ClientHelloSpec as-is 11 | // WARNING: there could be numerous subtle issues with ClientHelloSpecs 12 | // that are generated with this flag which could compromise security and/or mimicry 13 | AllowBluntMimicry bool 14 | // AlwaysAddPadding will always add a UtlsPaddingExtension with BoringPaddingStyle 15 | // at the end of the extensions list if it isn't found in the fingerprinted hello. 16 | // This could be useful in scenarios where the hello you are fingerprinting does not 17 | // have any padding, but you suspect that other changes you make to the final hello 18 | // (including things like different SNI lengths) would cause padding to be necessary 19 | AlwaysAddPadding bool 20 | 21 | RealPSKResumption bool // if set, PSK extension (if any) will be real PSK extension, otherwise it will be fake PSK extension 22 | } 23 | 24 | // FingerprintClientHello returns a ClientHelloSpec which is based on the 25 | // ClientHello that is passed in as the data argument 26 | // 27 | // If the ClientHello passed in has extensions that are not recognized or cannot be handled 28 | // it will return a non-nil error and a nil *ClientHelloSpec value 29 | // 30 | // The data should be the full tls record, including the record type/version/length header 31 | // as well as the handshake type/length/version header 32 | // https://tools.ietf.org/html/rfc5246#section-6.2 33 | // https://tools.ietf.org/html/rfc5246#section-7.4 34 | // 35 | // It calls UnmarshalClientHello internally, and is kept for backwards compatibility 36 | func (f *Fingerprinter) FingerprintClientHello(data []byte) (clientHelloSpec *ClientHelloSpec, err error) { 37 | return f.RawClientHello(data) 38 | } 39 | 40 | // RawClientHello returns a ClientHelloSpec which is based on the 41 | // ClientHello raw bytes that is passed in as the raw argument. 42 | // 43 | // It was renamed from FingerprintClientHello in v1.3.1 and earlier versions 44 | // as a more precise name for the function 45 | func (f *Fingerprinter) RawClientHello(raw []byte) (clientHelloSpec *ClientHelloSpec, err error) { 46 | clientHelloSpec = &ClientHelloSpec{} 47 | 48 | err = clientHelloSpec.FromRaw(raw, f.AllowBluntMimicry, f.RealPSKResumption) 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | if f.AlwaysAddPadding { 54 | clientHelloSpec.AlwaysAddPadding() 55 | } 56 | 57 | return clientHelloSpec, nil 58 | } 59 | 60 | // UnmarshalJSONClientHello returns a ClientHelloSpec which is based on the 61 | // ClientHello JSON bytes that is passed in as the json argument. 62 | func (f *Fingerprinter) UnmarshalJSONClientHello(json []byte) (clientHelloSpec *ClientHelloSpec, err error) { 63 | clientHelloSpec = &ClientHelloSpec{} 64 | err = clientHelloSpec.UnmarshalJSON(json) 65 | if err != nil { 66 | return nil, err 67 | } 68 | 69 | if f.AlwaysAddPadding { 70 | clientHelloSpec.AlwaysAddPadding() 71 | } 72 | 73 | return clientHelloSpec, nil 74 | } 75 | -------------------------------------------------------------------------------- /u_handshake_messages.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 uTLS Authors. 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 | "golang.org/x/crypto/cryptobyte" 9 | ) 10 | 11 | // Only implemented client-side, for server certificates. 12 | // Alternate certificate message formats (https://datatracker.ietf.org/doc/html/rfc7250) are not 13 | // supported. 14 | // https://datatracker.ietf.org/doc/html/rfc8879 15 | type utlsCompressedCertificateMsg struct { 16 | raw []byte 17 | 18 | algorithm uint16 19 | uncompressedLength uint32 // uint24 20 | compressedCertificateMessage []byte 21 | } 22 | 23 | func (m *utlsCompressedCertificateMsg) marshal() ([]byte, error) { 24 | if m.raw != nil { 25 | return m.raw, nil 26 | } 27 | 28 | var b cryptobyte.Builder 29 | b.AddUint8(utlsTypeCompressedCertificate) 30 | b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { 31 | b.AddUint16(m.algorithm) 32 | b.AddUint24(m.uncompressedLength) 33 | b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { 34 | b.AddBytes(m.compressedCertificateMessage) 35 | }) 36 | }) 37 | 38 | var err error 39 | m.raw, err = b.Bytes() 40 | return m.raw, err 41 | } 42 | 43 | func (m *utlsCompressedCertificateMsg) unmarshal(data []byte) bool { 44 | *m = utlsCompressedCertificateMsg{raw: data} 45 | s := cryptobyte.String(data) 46 | 47 | if !s.Skip(4) || // message type and uint24 length field 48 | !s.ReadUint16(&m.algorithm) || 49 | !s.ReadUint24(&m.uncompressedLength) || 50 | !readUint24LengthPrefixed(&s, &m.compressedCertificateMessage) { 51 | return false 52 | } 53 | return true 54 | } 55 | 56 | type utlsEncryptedExtensionsMsgExtraFields struct { 57 | applicationSettings []byte 58 | applicationSettingsCodepoint uint16 59 | echRetryConfigs []ECHConfig 60 | customExtension []byte 61 | } 62 | 63 | func (m *encryptedExtensionsMsg) utlsUnmarshal(extension uint16, extData cryptobyte.String) bool { 64 | switch extension { 65 | case utlsExtensionApplicationSettings: 66 | fallthrough 67 | case utlsExtensionApplicationSettingsNew: 68 | m.utls.applicationSettingsCodepoint = extension 69 | m.utls.applicationSettings = []byte(extData) 70 | case utlsExtensionECH: 71 | var err error 72 | m.utls.echRetryConfigs, err = UnmarshalECHConfigs([]byte(extData)) 73 | if err != nil { 74 | return false 75 | } 76 | } 77 | return true // success/unknown extension 78 | } 79 | 80 | type utlsClientEncryptedExtensionsMsg struct { 81 | raw []byte 82 | applicationSettings []byte 83 | applicationSettingsCodepoint uint16 84 | customExtension []byte 85 | } 86 | 87 | func (m *utlsClientEncryptedExtensionsMsg) marshal() (x []byte, err error) { 88 | if m.raw != nil { 89 | return m.raw, nil 90 | } 91 | 92 | var builder cryptobyte.Builder 93 | builder.AddUint8(typeEncryptedExtensions) 94 | builder.AddUint24LengthPrefixed(func(body *cryptobyte.Builder) { 95 | body.AddUint16LengthPrefixed(func(extensions *cryptobyte.Builder) { 96 | if m.applicationSettingsCodepoint != 0 { 97 | extensions.AddUint16(m.applicationSettingsCodepoint) 98 | extensions.AddUint16LengthPrefixed(func(msg *cryptobyte.Builder) { 99 | msg.AddBytes(m.applicationSettings) 100 | }) 101 | } 102 | if len(m.customExtension) > 0 { 103 | extensions.AddUint16(utlsFakeExtensionCustom) 104 | extensions.AddUint16LengthPrefixed(func(msg *cryptobyte.Builder) { 105 | msg.AddBytes(m.customExtension) 106 | }) 107 | } 108 | }) 109 | }) 110 | 111 | m.raw, err = builder.Bytes() 112 | return m.raw, err 113 | } 114 | 115 | func (m *utlsClientEncryptedExtensionsMsg) unmarshal(data []byte) bool { 116 | *m = utlsClientEncryptedExtensionsMsg{raw: data} 117 | s := cryptobyte.String(data) 118 | 119 | var extensions cryptobyte.String 120 | if !s.Skip(4) || // message type and uint24 length field 121 | !s.ReadUint16LengthPrefixed(&extensions) || !s.Empty() { 122 | return false 123 | } 124 | 125 | for !extensions.Empty() { 126 | var extension uint16 127 | var extData cryptobyte.String 128 | if !extensions.ReadUint16(&extension) || 129 | !extensions.ReadUint16LengthPrefixed(&extData) { 130 | return false 131 | } 132 | 133 | switch extension { 134 | case utlsExtensionApplicationSettings: 135 | fallthrough 136 | case utlsExtensionApplicationSettingsNew: 137 | m.applicationSettingsCodepoint = extension 138 | m.applicationSettings = []byte(extData) 139 | default: 140 | // Unknown extensions are illegal in EncryptedExtensions. 141 | return false 142 | } 143 | } 144 | return true 145 | } 146 | -------------------------------------------------------------------------------- /u_hpke.go: -------------------------------------------------------------------------------- 1 | package tls 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | "github.com/cloudflare/circl/hpke" 8 | "github.com/cloudflare/circl/kem" 9 | ) 10 | 11 | type HPKERawPublicKey = []byte 12 | type HPKE_KEM_ID = uint16 // RFC 9180 13 | type HPKE_KDF_ID = uint16 // RFC 9180 14 | type HPKE_AEAD_ID = uint16 // RFC 9180 15 | 16 | type HPKESymmetricCipherSuite struct { 17 | KdfId HPKE_KDF_ID 18 | AeadId HPKE_AEAD_ID 19 | } 20 | 21 | type HPKEKeyConfig struct { 22 | ConfigId uint8 23 | KemId HPKE_KEM_ID 24 | PublicKey kem.PublicKey 25 | rawPublicKey HPKERawPublicKey 26 | CipherSuites []HPKESymmetricCipherSuite 27 | } 28 | 29 | var defaultHPKESuite hpke.Suite 30 | 31 | func init() { 32 | var err error 33 | defaultHPKESuite, err = hpkeAssembleSuite( 34 | uint16(hpke.KEM_X25519_HKDF_SHA256), 35 | uint16(hpke.KDF_HKDF_SHA256), 36 | uint16(hpke.AEAD_AES128GCM), 37 | ) 38 | if err != nil { 39 | panic(fmt.Sprintf("hpke: mandatory-to-implement cipher suite not supported: %s", err)) 40 | } 41 | } 42 | 43 | func hpkeAssembleSuite(kemId, kdfId, aeadId uint16) (hpke.Suite, error) { 44 | kem := hpke.KEM(kemId) 45 | if !kem.IsValid() { 46 | return hpke.Suite{}, errors.New("KEM is not supported") 47 | } 48 | kdf := hpke.KDF(kdfId) 49 | if !kdf.IsValid() { 50 | return hpke.Suite{}, errors.New("KDF is not supported") 51 | } 52 | aead := hpke.AEAD(aeadId) 53 | if !aead.IsValid() { 54 | return hpke.Suite{}, errors.New("AEAD is not supported") 55 | } 56 | return hpke.NewSuite(kem, kdf, aead), nil 57 | } 58 | 59 | var dummyX25519PublicKey = []byte{ 60 | 143, 38, 37, 36, 12, 6, 229, 30, 140, 27, 167, 73, 26, 100, 203, 107, 216, 61 | 81, 163, 222, 52, 211, 54, 210, 46, 37, 78, 216, 157, 97, 241, 244, 62 | } 63 | -------------------------------------------------------------------------------- /u_key_schedule.go: -------------------------------------------------------------------------------- 1 | package tls 2 | 3 | import ( 4 | "crypto/mlkem" 5 | 6 | "golang.org/x/crypto/sha3" 7 | ) 8 | 9 | // kyberDecapsulate implements decapsulation according to Kyber Round 3. 10 | func kyberDecapsulate(dk *mlkem.DecapsulationKey768, c []byte) ([]byte, error) { 11 | K, err := dk.Decapsulate(c) 12 | if err != nil { 13 | return nil, err 14 | } 15 | return kyberSharedSecret(c, K), nil 16 | } 17 | 18 | func kyberSharedSecret(c, K []byte) []byte { 19 | // Package mlkem implements ML-KEM, which compared to Kyber removed a 20 | // final hashing step. Compute SHAKE-256(K || SHA3-256(c), 32) to match Kyber. 21 | // See https://words.filippo.io/mlkem768/#bonus-track-using-a-ml-kem-implementation-as-kyber-v3. 22 | h := sha3.NewShake256() 23 | h.Write(K) 24 | ch := sha3.New256() 25 | ch.Write(c) 26 | h.Write(ch.Sum(nil)) 27 | out := make([]byte, 32) 28 | h.Read(out) 29 | return out 30 | } 31 | -------------------------------------------------------------------------------- /u_prng.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Psiphon Inc. 3 | * All rights reserved. 4 | * 5 | * Released under utls licence: 6 | * https://github.com/refraction-networking/utls/blob/master/LICENSE 7 | */ 8 | 9 | // This code is a pared down version of: 10 | // https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/158caea562287284cc3fa5fcd1b3c97b1addf659/psiphon/common/prng/prng.go 11 | 12 | package tls 13 | 14 | import ( 15 | crypto_rand "crypto/rand" 16 | "encoding/binary" 17 | "io" 18 | "math" 19 | "math/rand" 20 | "sync" 21 | 22 | "golang.org/x/crypto/hkdf" 23 | "golang.org/x/crypto/sha3" 24 | ) 25 | 26 | const ( 27 | PRNGSeedLength = 32 28 | ) 29 | 30 | // PRNGSeed is a PRNG seed. 31 | type PRNGSeed [PRNGSeedLength]byte 32 | 33 | // NewPRNGSeed creates a new PRNG seed using crypto/rand.Read. 34 | func NewPRNGSeed() (*PRNGSeed, error) { 35 | seed := new(PRNGSeed) 36 | _, err := crypto_rand.Read(seed[:]) 37 | if err != nil { 38 | return nil, err 39 | } 40 | return seed, nil 41 | } 42 | 43 | // newSaltedPRNGSeed creates a new seed derived from an existing seed and a 44 | // salt. A HKDF is applied to the seed and salt. 45 | // 46 | // newSaltedPRNGSeed is intended for use cases where a single seed needs to be 47 | // used in distinct contexts to produce independent random streams. 48 | func newSaltedPRNGSeed(seed *PRNGSeed, salt string) (*PRNGSeed, error) { 49 | saltedSeed := new(PRNGSeed) 50 | _, err := io.ReadFull( 51 | hkdf.New(sha3.New256, seed[:], []byte(salt), nil), saltedSeed[:]) 52 | if err != nil { 53 | return nil, err 54 | } 55 | return saltedSeed, nil 56 | } 57 | 58 | // prng is a seeded, unbiased PRNG based on SHAKE256. that is suitable for use 59 | // cases such as obfuscation. Seeding is based on crypto/rand.Read. 60 | // 61 | // This PRNG is _not_ for security use cases including production cryptographic 62 | // key generation. 63 | // 64 | // It is safe to make concurrent calls to a PRNG instance. 65 | // 66 | // PRNG conforms to io.Reader and math/rand.Source, with additional helper 67 | // functions. 68 | type prng struct { 69 | rand *rand.Rand 70 | randomStreamMutex sync.Mutex 71 | randomStream sha3.ShakeHash 72 | } 73 | 74 | // newPRNG generates a seed and creates a PRNG with that seed. 75 | func newPRNG() (*prng, error) { 76 | seed, err := NewPRNGSeed() 77 | if err != nil { 78 | return nil, err 79 | } 80 | return newPRNGWithSeed(seed) 81 | } 82 | 83 | // newPRNGWithSeed initializes a new PRNG using an existing seed. 84 | func newPRNGWithSeed(seed *PRNGSeed) (*prng, error) { 85 | shake := sha3.NewShake256() 86 | _, err := shake.Write(seed[:]) 87 | if err != nil { 88 | return nil, err 89 | } 90 | p := &prng{ 91 | randomStream: shake, 92 | } 93 | p.rand = rand.New(p) 94 | return p, nil 95 | } 96 | 97 | // newPRNGWithSaltedSeed initializes a new PRNG using a seed derived from an 98 | // existing seed and a salt with NewSaltedSeed. 99 | func newPRNGWithSaltedSeed(seed *PRNGSeed, salt string) (*prng, error) { 100 | saltedSeed, err := newSaltedPRNGSeed(seed, salt) 101 | if err != nil { 102 | return nil, err 103 | } 104 | return newPRNGWithSeed(saltedSeed) 105 | } 106 | 107 | // Read reads random bytes from the PRNG stream into b. Read conforms to 108 | // io.Reader and always returns len(p), nil. 109 | func (p *prng) Read(b []byte) (int, error) { 110 | p.randomStreamMutex.Lock() 111 | defer p.randomStreamMutex.Unlock() 112 | 113 | // ShakeHash.Read never returns an error: 114 | // https://godoc.org/golang.org/x/crypto/sha3#ShakeHash 115 | _, _ = io.ReadFull(p.randomStream, b) 116 | 117 | return len(b), nil 118 | } 119 | 120 | // Int63 is equivalent to math/read.Int63. 121 | func (p *prng) Int63() int64 { 122 | i := p.Uint64() 123 | return int64(i & (1<<63 - 1)) 124 | } 125 | 126 | // Int63 is equivalent to math/read.Uint64. 127 | func (p *prng) Uint64() uint64 { 128 | var b [8]byte 129 | p.Read(b[:]) 130 | return binary.BigEndian.Uint64(b[:]) 131 | } 132 | 133 | // Seed must exist in order to use a PRNG as a math/rand.Source. This call is 134 | // not supported and ignored. 135 | func (p *prng) Seed(_ int64) { 136 | } 137 | 138 | // FlipWeightedCoin returns the result of a weighted 139 | // random coin flip. If the weight is 0.5, the outcome 140 | // is equally likely to be true or false. If the weight 141 | // is 1.0, the outcome is always true, and if the 142 | // weight is 0.0, the outcome is always false. 143 | // 144 | // Input weights > 1.0 are treated as 1.0. 145 | func (p *prng) FlipWeightedCoin(weight float64) bool { 146 | if weight > 1.0 { 147 | weight = 1.0 148 | } 149 | f := float64(p.Int63()) / float64(math.MaxInt64) 150 | return f > 1.0-weight 151 | } 152 | 153 | // Intn is equivalent to math/read.Intn, except it returns 0 if n <= 0 154 | // instead of panicking. 155 | func (p *prng) Intn(n int) int { 156 | if n <= 0 { 157 | return 0 158 | } 159 | return p.rand.Intn(n) 160 | } 161 | 162 | // Int63n is equivalent to math/read.Int63n, except it returns 0 if n <= 0 163 | // instead of panicking. 164 | func (p *prng) Int63n(n int64) int64 { 165 | if n <= 0 { 166 | return 0 167 | } 168 | return p.rand.Int63n(n) 169 | } 170 | 171 | // Intn is equivalent to math/read.Perm. 172 | func (p *prng) Perm(n int) []int { 173 | return p.rand.Perm(n) 174 | } 175 | 176 | // Range selects a random integer in [min, max]. 177 | // If min < 0, min is set to 0. If max < min, min is returned. 178 | func (p *prng) Range(min, max int) int { 179 | if min < 0 { 180 | min = 0 181 | } 182 | if max < min { 183 | return min 184 | } 185 | n := p.Intn(max - min + 1) 186 | n += min 187 | return n 188 | } 189 | -------------------------------------------------------------------------------- /u_quic_transport_parameters_test.go: -------------------------------------------------------------------------------- 1 | package tls 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | ) 7 | 8 | func TestMarshal(t *testing.T) { 9 | t.Run("Firefox", testTransportParametersFirefox) 10 | } 11 | 12 | func testTransportParametersFirefox(t *testing.T) { 13 | if !bytes.Equal(_inputTransportParametersFirefox.Marshal(), _truthTransportParametersFirefox) { 14 | t.Errorf("TransportParameters.Marshal() = %v, want %v", _inputTransportParametersFirefox.Marshal(), _truthTransportParametersFirefox) 15 | } 16 | } 17 | 18 | var ( 19 | _inputTransportParametersFirefox = TransportParameters{ 20 | InitialMaxStreamDataBidiRemote(0x100000), 21 | InitialMaxStreamsBidi(16), 22 | MaxDatagramFrameSize(1200), 23 | MaxIdleTimeout(30000), 24 | ActiveConnectionIDLimit(8), 25 | &GREASEQUICBit{}, 26 | &VersionInformation{ 27 | ChoosenVersion: 0x00000001, 28 | AvailableVersions: []uint32{ 29 | 0x8acafaea, 30 | 0x00000001, 31 | }, 32 | LegacyID: true, 33 | }, 34 | InitialMaxStreamsUni(16), 35 | &GREASETransportParameter{ 36 | IdOverride: 0xff02de1a, 37 | ValueOverride: []byte{ 38 | 0x43, 0xe8, 39 | }, 40 | }, 41 | InitialMaxStreamDataBidiLocal(0xc00000), 42 | InitialMaxStreamDataUni(0x100000), 43 | InitialSourceConnectionID([]byte{0x53, 0xf0, 0xb2}), 44 | MaxAckDelay(20), 45 | InitialMaxData(0x1800000), 46 | &DisableActiveMigration{}, 47 | } 48 | _truthTransportParametersFirefox = []byte{ 49 | 0x06, 0x04, 0x80, 0x10, 50 | 0x00, 0x00, 0x08, 0x01, 51 | 0x10, 0x20, 0x02, 0x44, 52 | 0xb0, 0x01, 0x04, 0x80, 53 | 0x00, 0x75, 0x30, 0x0e, 54 | 0x01, 0x08, 0x6a, 0xb2, 55 | 0x00, 0x80, 0xff, 0x73, 56 | 0xdb, 0x0c, 0x00, 0x00, 57 | 0x00, 0x01, 0x8a, 0xca, 58 | 0xfa, 0xea, 0x00, 0x00, 59 | 0x00, 0x01, 0x09, 0x01, 60 | 0x10, 0xc0, 0x00, 0x00, 61 | 0x00, 0xff, 0x02, 0xde, 62 | 0x1a, 0x02, 0x43, 0xe8, 63 | 0x05, 0x04, 0x80, 0xc0, 64 | 0x00, 0x00, 0x07, 0x04, 65 | 0x80, 0x10, 0x00, 0x00, 66 | 0x0f, 0x03, 0x53, 0xf0, 67 | 0xb2, 0x0b, 0x01, 0x14, 68 | 0x04, 0x04, 0x81, 0x80, 69 | 0x00, 0x00, 0x0c, 0x00, 70 | } 71 | ) 72 | -------------------------------------------------------------------------------- /u_roller.go: -------------------------------------------------------------------------------- 1 | package tls 2 | 3 | import ( 4 | "net" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | type Roller struct { 10 | HelloIDs []ClientHelloID 11 | HelloIDMu sync.Mutex 12 | WorkingHelloID *ClientHelloID 13 | TcpDialTimeout time.Duration 14 | TlsHandshakeTimeout time.Duration 15 | r *prng 16 | } 17 | 18 | // NewRoller creates Roller object with default range of HelloIDs to cycle through until a 19 | // working/unblocked one is found. 20 | func NewRoller() (*Roller, error) { 21 | r, err := newPRNG() 22 | if err != nil { 23 | return nil, err 24 | } 25 | 26 | tcpDialTimeoutInc := r.Intn(14) 27 | tcpDialTimeoutInc = 7 + tcpDialTimeoutInc 28 | 29 | tlsHandshakeTimeoutInc := r.Intn(20) 30 | tlsHandshakeTimeoutInc = 11 + tlsHandshakeTimeoutInc 31 | 32 | return &Roller{ 33 | HelloIDs: []ClientHelloID{ 34 | HelloChrome_Auto, 35 | HelloFirefox_Auto, 36 | HelloIOS_Auto, 37 | HelloRandomized, 38 | }, 39 | TcpDialTimeout: time.Second * time.Duration(tcpDialTimeoutInc), 40 | TlsHandshakeTimeout: time.Second * time.Duration(tlsHandshakeTimeoutInc), 41 | r: r, 42 | }, nil 43 | } 44 | 45 | // Dial attempts to establish connection to given address using different HelloIDs. 46 | // If a working HelloID is found, it is used again for subsequent Dials. 47 | // If tcp connection fails or all HelloIDs are tried, returns with last error. 48 | // 49 | // Usage examples: 50 | // Dial("tcp4", "google.com:443", "google.com") 51 | // Dial("tcp", "10.23.144.22:443", "mywebserver.org") 52 | func (c *Roller) Dial(network, addr, serverName string) (*UConn, error) { 53 | helloIDs := make([]ClientHelloID, len(c.HelloIDs)) 54 | copy(helloIDs, c.HelloIDs) 55 | c.r.rand.Shuffle(len(c.HelloIDs), func(i, j int) { 56 | helloIDs[i], helloIDs[j] = helloIDs[j], helloIDs[i] 57 | }) 58 | 59 | c.HelloIDMu.Lock() 60 | workingHelloId := c.WorkingHelloID // keep using same helloID, if it works 61 | c.HelloIDMu.Unlock() 62 | if workingHelloId != nil { 63 | helloIDFound := false 64 | for i, ID := range helloIDs { 65 | if ID == *workingHelloId { 66 | helloIDs[i] = helloIDs[0] 67 | helloIDs[0] = *workingHelloId // push working hello ID first 68 | helloIDFound = true 69 | break 70 | } 71 | } 72 | if !helloIDFound { 73 | helloIDs = append([]ClientHelloID{*workingHelloId}, helloIDs...) 74 | } 75 | } 76 | 77 | var tcpConn net.Conn 78 | var err error 79 | for _, helloID := range helloIDs { 80 | tcpConn, err = net.DialTimeout(network, addr, c.TcpDialTimeout) 81 | if err != nil { 82 | return nil, err // on tcp Dial failure return with error right away 83 | } 84 | 85 | client := UClient(tcpConn, nil, helloID) 86 | client.SetSNI(serverName) 87 | client.SetDeadline(time.Now().Add(c.TlsHandshakeTimeout)) 88 | err = client.Handshake() 89 | client.SetDeadline(time.Time{}) // unset timeout 90 | if err != nil { 91 | continue // on tls Dial error keep trying HelloIDs 92 | } 93 | 94 | c.HelloIDMu.Lock() 95 | c.WorkingHelloID = &client.ClientHelloID 96 | c.HelloIDMu.Unlock() 97 | return client, err 98 | } 99 | return nil, err 100 | } 101 | -------------------------------------------------------------------------------- /u_session_ticket.go: -------------------------------------------------------------------------------- 1 | package tls 2 | 3 | import "io" 4 | 5 | type ISessionTicketExtension interface { 6 | TLSExtension 7 | 8 | // If false is returned, utls will invoke `InitializeByUtls()` for the necessary initialization. 9 | Initializable 10 | 11 | // InitializeByUtls is invoked when IsInitialized() returns false. 12 | // It initializes the extension using a real and valid TLS 1.2 session. 13 | InitializeByUtls(session *SessionState, ticket []byte) 14 | 15 | GetSession() *SessionState 16 | 17 | GetTicket() []byte 18 | } 19 | 20 | // SessionTicketExtension implements session_ticket (35) 21 | type SessionTicketExtension struct { 22 | Session *SessionState 23 | Ticket []byte 24 | Initialized bool 25 | } 26 | 27 | func (e *SessionTicketExtension) writeToUConn(uc *UConn) error { 28 | // session states are handled later. At this point tickets aren't 29 | // being loaded by utls, so don't write anything to the UConn. 30 | uc.HandshakeState.Hello.TicketSupported = true // This doesn't really matter, this field is only used to add session ticket ext in go tls. 31 | return nil 32 | } 33 | 34 | func (e *SessionTicketExtension) Len() int { 35 | return 4 + len(e.Ticket) 36 | } 37 | 38 | func (e *SessionTicketExtension) Read(b []byte) (int, error) { 39 | if len(b) < e.Len() { 40 | return 0, io.ErrShortBuffer 41 | } 42 | 43 | extBodyLen := e.Len() - 4 44 | 45 | b[0] = byte(extensionSessionTicket >> 8) 46 | b[1] = byte(extensionSessionTicket) 47 | b[2] = byte(extBodyLen >> 8) 48 | b[3] = byte(extBodyLen) 49 | if extBodyLen > 0 { 50 | copy(b[4:], e.Ticket) 51 | } 52 | return e.Len(), io.EOF 53 | } 54 | 55 | func (e *SessionTicketExtension) IsInitialized() bool { 56 | return e.Initialized 57 | } 58 | 59 | func (e *SessionTicketExtension) InitializeByUtls(session *SessionState, ticket []byte) { 60 | uAssert(!e.Initialized, "tls: InitializeByUtls failed: the SessionTicketExtension is initialized") 61 | uAssert(session.version == VersionTLS12 && session != nil && ticket != nil, "tls: InitializeByUtls failed: the session is not a tls 1.2 session") 62 | e.Session = session 63 | e.Ticket = ticket 64 | e.Initialized = true 65 | } 66 | 67 | func (e *SessionTicketExtension) UnmarshalJSON(_ []byte) error { 68 | return nil // no-op 69 | } 70 | 71 | func (e *SessionTicketExtension) Write(_ []byte) (int, error) { 72 | // RFC 5077, Section 3.2 73 | return 0, nil 74 | } 75 | 76 | func (e *SessionTicketExtension) GetSession() *SessionState { 77 | return e.Session 78 | } 79 | 80 | func (e *SessionTicketExtension) GetTicket() []byte { 81 | return e.Ticket 82 | } 83 | --------------------------------------------------------------------------------