├── .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 |
--------------------------------------------------------------------------------