reorganize code, add json/v2 endpoint and API doc
This commit is contained in:
parent
7af54c28e1
commit
fe085af75c
|
@ -1,2 +1 @@
|
|||
/build/
|
||||
/TODO
|
||||
|
|
|
@ -14,3 +14,7 @@ License: BSD-3-Clause
|
|||
Files: *.gmi
|
||||
Copyright: 2022-2023 nervuri <https://nervuri.net/contact>
|
||||
License: BSD-3-Clause
|
||||
|
||||
Files: clienthello/*.csv
|
||||
Copyright: IANA and IETF
|
||||
License: CC0-1.0
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
-->
|
||||
|
||||
# API Documentation
|
||||
|
||||
The API is largely stable - fields may be added, but existing fields will not be modified or removed.
|
||||
|
||||
There are two JSON endpoints:
|
||||
|
||||
* [/json/v1](https://tlsprivacy.nervuri.net/json/v1) - basic
|
||||
* [/json/v2](https://tlsprivacy.nervuri.net/json/v2) - detailed
|
||||
|
||||
The `v2` endpoint expands numeric identifiers (of TLS versions, cipher suites, signature algorithms, etc) into objects containing more information. The `name` field in these objects is taken from [the IANA registries](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml); note that these names may differ from those used in TLS libraries ([example](https://ciphersuite.info/cs/TLS_DHE_DSS_WITH_AES_256_CBC_SHA256/)).
|
||||
|
||||
The `v1` endpoint is not deprecated, it is a lighter version of `v2`. `v1` is a better fit for CI tests, while `v2` might be preferable on the user-facing side, where you would rather use names instead of numeric identifiers.
|
||||
|
||||
The outline of the `v1` output is:
|
||||
|
||||
```
|
||||
{
|
||||
"client_hello": {
|
||||
"raw": "...",
|
||||
"record_header_tls_version": 769,
|
||||
"client_tls_version": 771,
|
||||
"random": "...",
|
||||
"session_id": "...",
|
||||
"cipher_suites": [
|
||||
...
|
||||
],
|
||||
"compression_methods": [
|
||||
0
|
||||
],
|
||||
"extensions": [
|
||||
...
|
||||
],
|
||||
"highlights": {
|
||||
"gmt_unix_time": 3563154493,
|
||||
"secure_renegotiation_support": true,
|
||||
"ocsp_stapling_support": false,
|
||||
"sct_support": false,
|
||||
"ja3": "...",
|
||||
"ja3_md5": "..."
|
||||
}
|
||||
},
|
||||
"connection_info": {
|
||||
"tls_version": 772,
|
||||
"cipher_suite": 4867,
|
||||
"session_resumed": false,
|
||||
"alpn_negotiated_protocol": "http/1.1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `client_hello` object contains a `highlights` object, which includes:
|
||||
|
||||
* the deprecated `gmt_unix_time` value extracted from the client random, which [should NOT](https://datatracker.ietf.org/doc/html/draft-mathewson-no-gmtunixtime) represent the current timestamp anymore;
|
||||
* boolean values that show whether the client supports secure renegotiation, OCSP stapling and SCTs (Signed Certificate Timestamps);
|
||||
* the JA3 fingerprint, both its expanded form and its MD5 hash.
|
||||
|
||||
Aside from `client_hello`, there is a `connection_info` object containing the TLS version, cipher suite and ALPN protocol that were negotiated for the connection, as well as a boolean value that shows whether the TLS session was resumed.
|
||||
|
||||
In `v2` numeric identifiers are expanded, for example `"cipher_suite": 4867` becomes:
|
||||
|
||||
```
|
||||
"cipher_suite": {
|
||||
"code": 4867,
|
||||
"hex_code": "1303",
|
||||
"name": "TLS_CHACHA20_POLY1305_SHA256"
|
||||
},
|
||||
```
|
||||
|
||||
More info (such as whether a cipher suite is recommended or not) may be added later.
|
||||
|
||||
In both JSON endpoints, raw byte values are represented as hexadecimal strings.
|
||||
|
||||
IANA-assigned codes for TLS parameters and extensions are documented at:
|
||||
|
||||
* [TLS parameters](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml)
|
||||
* [TLS extensions](https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml)
|
|
@ -32,7 +32,7 @@ Generate TLS certificate:
|
|||
# CA-signed:
|
||||
certbot certonly --webroot -w /var/www/example.com -d example.com
|
||||
# or self-signed:
|
||||
openssl req -new -subj "/CN=example.com" -x509 -days 36500 -nodes -out cert.pem -keyout privkey.pem
|
||||
openssl req -new -subj "/CN=example.com" -addext "subjectAltName = DNS:example.com" -x509 -days 36500 -nodes -out cert.pem -keyout privkey.pem
|
||||
```
|
||||
|
||||
Run on port 1965:
|
||||
|
@ -55,7 +55,7 @@ After=network.target
|
|||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
ExecStart=client-hello-mirror -u www-data -c /etc/letsencrypt/live/example.org/fullchain.pem -k /etc/letsencrypt/live/example.org/privkey.pem :443 2>/var/log/client-hello-mirror-error.log
|
||||
ExecStart=client-hello-mirror -u www-data -c /etc/letsencrypt/live/example.com/fullchain.pem -k /etc/letsencrypt/live/example.com/privkey.pem :443 2>/var/log/client-hello-mirror-error.log
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
5
Makefile
5
Makefile
|
@ -7,9 +7,8 @@ dev: check
|
|||
go build -o build/client-hello-mirror
|
||||
|
||||
check:
|
||||
#go fmt
|
||||
#golangci-lint run
|
||||
go vet
|
||||
golangci-lint run
|
||||
#go vet
|
||||
#go test
|
||||
find . -name '*.html' -exec xmllint --noout {} \;
|
||||
find . -name '*.html' -exec sh -c 'tidy -q -errors -access "{}" || ls "{}"' \;
|
||||
|
|
14
README.md
14
README.md
|
@ -13,24 +13,20 @@ This test:
|
|||
* supports both HTTP and [Gemini](https://gemini.circumlunar.space/) on the same port;
|
||||
* is [free as in freedom](https://www.gnu.org/philosophy/free-sw.en.html) and trivial to self-host.
|
||||
|
||||
The API is largely stable - fields may be added, but existing fields will not be modified or removed. IANA-assigned codes for TLS parameters and extensions are documented at:
|
||||
|
||||
* [TLS parameters](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml)
|
||||
* [TLS extensions](https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml)
|
||||
|
||||
Note that these lists do not include draft extensions and [GREASE](https://datatracker.ietf.org/doc/html/rfc8701) values. Missing values will be documented here as the project evolves.
|
||||
|
||||
## Installation
|
||||
|
||||
See [INSTALL.md](INSTALL.md).
|
||||
|
||||
## API documentation
|
||||
|
||||
This test exposes two JSON endpoints: [/json/v1 (basic)](https://tlsprivacy.nervuri.net/json/v1) and [/json/v2 (detailed)](https://tlsprivacy.nervuri.net/json/v2). See [DOC.md](DOC.md) for details.
|
||||
|
||||
## Roadmap
|
||||
|
||||
* HTML & gemtext front-end
|
||||
* documentation
|
||||
* detect client vulnerability to session [prolongation attacks](https://svs.informatik.uni-hamburg.de/publications/2018/2018-12-06-Sy-ACSAC-Tracking_Users_across_the_Web_via_TLS_Session_Resumption.pdf#page=3)
|
||||
* support sessionID-based resumption (Go's `crypto/tls` library currently does not)
|
||||
* support early data / 0-RTT (Go's `crypto/tls` library currently does not)
|
||||
* support sessionID-based resumption (Go's `crypto/tls` library currently does not)
|
||||
|
||||
## Contributing
|
||||
|
||||
|
|
|
@ -0,0 +1,449 @@
|
|||
Value,Description,DTLS-OK,Recommended,Reference
|
||||
"0x00,0x00",TLS_NULL_WITH_NULL_NULL,Y,N,[RFC5246]
|
||||
"0x00,0x01",TLS_RSA_WITH_NULL_MD5,Y,N,[RFC5246]
|
||||
"0x00,0x02",TLS_RSA_WITH_NULL_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x03",TLS_RSA_EXPORT_WITH_RC4_40_MD5,N,N,[RFC4346][RFC6347]
|
||||
"0x00,0x04",TLS_RSA_WITH_RC4_128_MD5,N,N,[RFC5246][RFC6347]
|
||||
"0x00,0x05",TLS_RSA_WITH_RC4_128_SHA,N,N,[RFC5246][RFC6347]
|
||||
"0x00,0x06",TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,Y,N,[RFC4346]
|
||||
"0x00,0x07",TLS_RSA_WITH_IDEA_CBC_SHA,Y,N,[RFC5469][status-change-tls-des-idea-ciphers-to-historic]
|
||||
"0x00,0x08",TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,Y,N,[RFC4346]
|
||||
"0x00,0x09",TLS_RSA_WITH_DES_CBC_SHA,Y,N,[RFC5469][status-change-tls-des-idea-ciphers-to-historic]
|
||||
"0x00,0x0A",TLS_RSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x0B",TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,Y,N,[RFC4346]
|
||||
"0x00,0x0C",TLS_DH_DSS_WITH_DES_CBC_SHA,Y,N,[RFC5469][status-change-tls-des-idea-ciphers-to-historic]
|
||||
"0x00,0x0D",TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x0E",TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,Y,N,[RFC4346]
|
||||
"0x00,0x0F",TLS_DH_RSA_WITH_DES_CBC_SHA,Y,N,[RFC5469][status-change-tls-des-idea-ciphers-to-historic]
|
||||
"0x00,0x10",TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x11",TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,Y,N,[RFC4346]
|
||||
"0x00,0x12",TLS_DHE_DSS_WITH_DES_CBC_SHA,Y,N,[RFC5469][status-change-tls-des-idea-ciphers-to-historic]
|
||||
"0x00,0x13",TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x14",TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,Y,N,[RFC4346]
|
||||
"0x00,0x15",TLS_DHE_RSA_WITH_DES_CBC_SHA,Y,N,[RFC5469][status-change-tls-des-idea-ciphers-to-historic]
|
||||
"0x00,0x16",TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x17",TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,N,N,[RFC4346][RFC6347]
|
||||
"0x00,0x18",TLS_DH_anon_WITH_RC4_128_MD5,N,N,[RFC5246][RFC6347]
|
||||
"0x00,0x19",TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,Y,N,[RFC4346]
|
||||
"0x00,0x1A",TLS_DH_anon_WITH_DES_CBC_SHA,Y,N,[RFC5469][status-change-tls-des-idea-ciphers-to-historic]
|
||||
"0x00,0x1B",TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x1C-1D",Reserved to avoid conflicts with SSLv3,,,[RFC5246]
|
||||
"0x00,0x1E",TLS_KRB5_WITH_DES_CBC_SHA,Y,N,[RFC2712]
|
||||
"0x00,0x1F",TLS_KRB5_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC2712]
|
||||
"0x00,0x20",TLS_KRB5_WITH_RC4_128_SHA,N,N,[RFC2712][RFC6347]
|
||||
"0x00,0x21",TLS_KRB5_WITH_IDEA_CBC_SHA,Y,N,[RFC2712]
|
||||
"0x00,0x22",TLS_KRB5_WITH_DES_CBC_MD5,Y,N,[RFC2712]
|
||||
"0x00,0x23",TLS_KRB5_WITH_3DES_EDE_CBC_MD5,Y,N,[RFC2712]
|
||||
"0x00,0x24",TLS_KRB5_WITH_RC4_128_MD5,N,N,[RFC2712][RFC6347]
|
||||
"0x00,0x25",TLS_KRB5_WITH_IDEA_CBC_MD5,Y,N,[RFC2712]
|
||||
"0x00,0x26",TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,Y,N,[RFC2712]
|
||||
"0x00,0x27",TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,Y,N,[RFC2712]
|
||||
"0x00,0x28",TLS_KRB5_EXPORT_WITH_RC4_40_SHA,N,N,[RFC2712][RFC6347]
|
||||
"0x00,0x29",TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,Y,N,[RFC2712]
|
||||
"0x00,0x2A",TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5,Y,N,[RFC2712]
|
||||
"0x00,0x2B",TLS_KRB5_EXPORT_WITH_RC4_40_MD5,N,N,[RFC2712][RFC6347]
|
||||
"0x00,0x2C",TLS_PSK_WITH_NULL_SHA,Y,N,[RFC4785]
|
||||
"0x00,0x2D",TLS_DHE_PSK_WITH_NULL_SHA,Y,N,[RFC4785]
|
||||
"0x00,0x2E",TLS_RSA_PSK_WITH_NULL_SHA,Y,N,[RFC4785]
|
||||
"0x00,0x2F",TLS_RSA_WITH_AES_128_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x30",TLS_DH_DSS_WITH_AES_128_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x31",TLS_DH_RSA_WITH_AES_128_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x32",TLS_DHE_DSS_WITH_AES_128_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x33",TLS_DHE_RSA_WITH_AES_128_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x34",TLS_DH_anon_WITH_AES_128_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x35",TLS_RSA_WITH_AES_256_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x36",TLS_DH_DSS_WITH_AES_256_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x37",TLS_DH_RSA_WITH_AES_256_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x38",TLS_DHE_DSS_WITH_AES_256_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x39",TLS_DHE_RSA_WITH_AES_256_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x3A",TLS_DH_anon_WITH_AES_256_CBC_SHA,Y,N,[RFC5246]
|
||||
"0x00,0x3B",TLS_RSA_WITH_NULL_SHA256,Y,N,[RFC5246]
|
||||
"0x00,0x3C",TLS_RSA_WITH_AES_128_CBC_SHA256,Y,N,[RFC5246]
|
||||
"0x00,0x3D",TLS_RSA_WITH_AES_256_CBC_SHA256,Y,N,[RFC5246]
|
||||
"0x00,0x3E",TLS_DH_DSS_WITH_AES_128_CBC_SHA256,Y,N,[RFC5246]
|
||||
"0x00,0x3F",TLS_DH_RSA_WITH_AES_128_CBC_SHA256,Y,N,[RFC5246]
|
||||
"0x00,0x40",TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,Y,N,[RFC5246]
|
||||
"0x00,0x41",TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,Y,N,[RFC5932]
|
||||
"0x00,0x42",TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,Y,N,[RFC5932]
|
||||
"0x00,0x43",TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,Y,N,[RFC5932]
|
||||
"0x00,0x44",TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,Y,N,[RFC5932]
|
||||
"0x00,0x45",TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,Y,N,[RFC5932]
|
||||
"0x00,0x46",TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,Y,N,[RFC5932]
|
||||
"0x00,0x47-4F","Reserved to avoid conflicts with
|
||||
deployed implementations",,,[Pasi_Eronen]
|
||||
"0x00,0x50-58",Reserved to avoid conflicts,,,"[Pasi Eronen, <pasi.eronen&nokia.com>, 2008-04-04. 2008-04-04]"
|
||||
"0x00,0x59-5C","Reserved to avoid conflicts with
|
||||
deployed implementations",,,[Pasi_Eronen]
|
||||
"0x00,0x5D-5F",Unassigned,,,
|
||||
"0x00,0x60-66","Reserved to avoid conflicts with
|
||||
widely deployed implementations",,,[Pasi_Eronen]
|
||||
"0x00,0x67",TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,Y,N,[RFC5246]
|
||||
"0x00,0x68",TLS_DH_DSS_WITH_AES_256_CBC_SHA256,Y,N,[RFC5246]
|
||||
"0x00,0x69",TLS_DH_RSA_WITH_AES_256_CBC_SHA256,Y,N,[RFC5246]
|
||||
"0x00,0x6A",TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,Y,N,[RFC5246]
|
||||
"0x00,0x6B",TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,Y,N,[RFC5246]
|
||||
"0x00,0x6C",TLS_DH_anon_WITH_AES_128_CBC_SHA256,Y,N,[RFC5246]
|
||||
"0x00,0x6D",TLS_DH_anon_WITH_AES_256_CBC_SHA256,Y,N,[RFC5246]
|
||||
"0x00,0x6E-83",Unassigned,,,
|
||||
"0x00,0x84",TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,Y,N,[RFC5932]
|
||||
"0x00,0x85",TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,Y,N,[RFC5932]
|
||||
"0x00,0x86",TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,Y,N,[RFC5932]
|
||||
"0x00,0x87",TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,Y,N,[RFC5932]
|
||||
"0x00,0x88",TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,Y,N,[RFC5932]
|
||||
"0x00,0x89",TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,Y,N,[RFC5932]
|
||||
"0x00,0x8A",TLS_PSK_WITH_RC4_128_SHA,N,N,[RFC4279][RFC6347]
|
||||
"0x00,0x8B",TLS_PSK_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC4279]
|
||||
"0x00,0x8C",TLS_PSK_WITH_AES_128_CBC_SHA,Y,N,[RFC4279]
|
||||
"0x00,0x8D",TLS_PSK_WITH_AES_256_CBC_SHA,Y,N,[RFC4279]
|
||||
"0x00,0x8E",TLS_DHE_PSK_WITH_RC4_128_SHA,N,N,[RFC4279][RFC6347]
|
||||
"0x00,0x8F",TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC4279]
|
||||
"0x00,0x90",TLS_DHE_PSK_WITH_AES_128_CBC_SHA,Y,N,[RFC4279]
|
||||
"0x00,0x91",TLS_DHE_PSK_WITH_AES_256_CBC_SHA,Y,N,[RFC4279]
|
||||
"0x00,0x92",TLS_RSA_PSK_WITH_RC4_128_SHA,N,N,[RFC4279][RFC6347]
|
||||
"0x00,0x93",TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC4279]
|
||||
"0x00,0x94",TLS_RSA_PSK_WITH_AES_128_CBC_SHA,Y,N,[RFC4279]
|
||||
"0x00,0x95",TLS_RSA_PSK_WITH_AES_256_CBC_SHA,Y,N,[RFC4279]
|
||||
"0x00,0x96",TLS_RSA_WITH_SEED_CBC_SHA,Y,N,[RFC4162]
|
||||
"0x00,0x97",TLS_DH_DSS_WITH_SEED_CBC_SHA,Y,N,[RFC4162]
|
||||
"0x00,0x98",TLS_DH_RSA_WITH_SEED_CBC_SHA,Y,N,[RFC4162]
|
||||
"0x00,0x99",TLS_DHE_DSS_WITH_SEED_CBC_SHA,Y,N,[RFC4162]
|
||||
"0x00,0x9A",TLS_DHE_RSA_WITH_SEED_CBC_SHA,Y,N,[RFC4162]
|
||||
"0x00,0x9B",TLS_DH_anon_WITH_SEED_CBC_SHA,Y,N,[RFC4162]
|
||||
"0x00,0x9C",TLS_RSA_WITH_AES_128_GCM_SHA256,Y,N,[RFC5288]
|
||||
"0x00,0x9D",TLS_RSA_WITH_AES_256_GCM_SHA384,Y,N,[RFC5288]
|
||||
"0x00,0x9E",TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,Y,Y,[RFC5288]
|
||||
"0x00,0x9F",TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,Y,Y,[RFC5288]
|
||||
"0x00,0xA0",TLS_DH_RSA_WITH_AES_128_GCM_SHA256,Y,N,[RFC5288]
|
||||
"0x00,0xA1",TLS_DH_RSA_WITH_AES_256_GCM_SHA384,Y,N,[RFC5288]
|
||||
"0x00,0xA2",TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,Y,N,[RFC5288]
|
||||
"0x00,0xA3",TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,Y,N,[RFC5288]
|
||||
"0x00,0xA4",TLS_DH_DSS_WITH_AES_128_GCM_SHA256,Y,N,[RFC5288]
|
||||
"0x00,0xA5",TLS_DH_DSS_WITH_AES_256_GCM_SHA384,Y,N,[RFC5288]
|
||||
"0x00,0xA6",TLS_DH_anon_WITH_AES_128_GCM_SHA256,Y,N,[RFC5288]
|
||||
"0x00,0xA7",TLS_DH_anon_WITH_AES_256_GCM_SHA384,Y,N,[RFC5288]
|
||||
"0x00,0xA8",TLS_PSK_WITH_AES_128_GCM_SHA256,Y,N,[RFC5487]
|
||||
"0x00,0xA9",TLS_PSK_WITH_AES_256_GCM_SHA384,Y,N,[RFC5487]
|
||||
"0x00,0xAA",TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,Y,Y,[RFC5487]
|
||||
"0x00,0xAB",TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,Y,Y,[RFC5487]
|
||||
"0x00,0xAC",TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,Y,N,[RFC5487]
|
||||
"0x00,0xAD",TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,Y,N,[RFC5487]
|
||||
"0x00,0xAE",TLS_PSK_WITH_AES_128_CBC_SHA256,Y,N,[RFC5487]
|
||||
"0x00,0xAF",TLS_PSK_WITH_AES_256_CBC_SHA384,Y,N,[RFC5487]
|
||||
"0x00,0xB0",TLS_PSK_WITH_NULL_SHA256,Y,N,[RFC5487]
|
||||
"0x00,0xB1",TLS_PSK_WITH_NULL_SHA384,Y,N,[RFC5487]
|
||||
"0x00,0xB2",TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,Y,N,[RFC5487]
|
||||
"0x00,0xB3",TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,Y,N,[RFC5487]
|
||||
"0x00,0xB4",TLS_DHE_PSK_WITH_NULL_SHA256,Y,N,[RFC5487]
|
||||
"0x00,0xB5",TLS_DHE_PSK_WITH_NULL_SHA384,Y,N,[RFC5487]
|
||||
"0x00,0xB6",TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,Y,N,[RFC5487]
|
||||
"0x00,0xB7",TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,Y,N,[RFC5487]
|
||||
"0x00,0xB8",TLS_RSA_PSK_WITH_NULL_SHA256,Y,N,[RFC5487]
|
||||
"0x00,0xB9",TLS_RSA_PSK_WITH_NULL_SHA384,Y,N,[RFC5487]
|
||||
"0x00,0xBA",TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC5932]
|
||||
"0x00,0xBB",TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC5932]
|
||||
"0x00,0xBC",TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC5932]
|
||||
"0x00,0xBD",TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC5932]
|
||||
"0x00,0xBE",TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC5932]
|
||||
"0x00,0xBF",TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC5932]
|
||||
"0x00,0xC0",TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,Y,N,[RFC5932]
|
||||
"0x00,0xC1",TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,Y,N,[RFC5932]
|
||||
"0x00,0xC2",TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256,Y,N,[RFC5932]
|
||||
"0x00,0xC3",TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,Y,N,[RFC5932]
|
||||
"0x00,0xC4",TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,Y,N,[RFC5932]
|
||||
"0x00,0xC5",TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,Y,N,[RFC5932]
|
||||
"0x00,0xC6",TLS_SM4_GCM_SM3,N,N,[RFC8998]
|
||||
"0x00,0xC7",TLS_SM4_CCM_SM3,N,N,[RFC8998]
|
||||
"0x00,0xC8-FE",Unassigned,,,
|
||||
"0x00,0xFF",TLS_EMPTY_RENEGOTIATION_INFO_SCSV,Y,N,[RFC5746]
|
||||
"0x01-09,*",Unassigned,,,
|
||||
"0x0A,0x00-09",Unassigned,,,
|
||||
"0x0A,0x0A",Reserved,Y,N,[RFC8701]
|
||||
"0x0A,0x0B-FF",Unassigned,,,
|
||||
"0x0B-12,*",Unassigned,,,
|
||||
"0x13,0x00",Unassigned,,,
|
||||
"0x13,0x01",TLS_AES_128_GCM_SHA256,Y,Y,[RFC8446]
|
||||
"0x13,0x02",TLS_AES_256_GCM_SHA384,Y,Y,[RFC8446]
|
||||
"0x13,0x03",TLS_CHACHA20_POLY1305_SHA256,Y,Y,[RFC8446]
|
||||
"0x13,0x04",TLS_AES_128_CCM_SHA256,Y,Y,[RFC8446]
|
||||
"0x13,0x05",TLS_AES_128_CCM_8_SHA256,Y,N,[RFC8446][IESG Action 2018-08-16]
|
||||
"0x13,0x06",TLS_AEGIS_256_SHA384,Y,N,[draft-irtf-cfrg-aegis-aead-00]
|
||||
"0x13,0x07",TLS_AEGIS_128L_SHA256,Y,N,[draft-irtf-cfrg-aegis-aead-00]
|
||||
"0x13,0x08-FF",Unassigned,,,
|
||||
"0x14-19,*",Unassigned,,,
|
||||
"0x1A,0x00-19",Unassigned,,,
|
||||
"0x1A,0x1A",Reserved,Y,N,[RFC8701]
|
||||
"0x1A,0x1B-FF",Unassigned,,,
|
||||
"0x1B-29,*",Unassigned,,,
|
||||
"0x2A,0x00-29",Unassigned,,,
|
||||
"0x2A,0x2A",Reserved,Y,N,[RFC8701]
|
||||
"0x2A,0x2B-FF",Unassigned,,,
|
||||
"0x2B-39,*",Unassigned,,,
|
||||
"0x3A,0x00-39",Unassigned,,,
|
||||
"0x3A,0x3A",Reserved,Y,N,[RFC8701]
|
||||
"0x3A,0x3B-FF",Unassigned,,,
|
||||
"0x3B-49,*",Unassigned,,,
|
||||
"0x4A,0x00-49",Unassigned,,,
|
||||
"0x4A,0x4A",Reserved,Y,N,[RFC8701]
|
||||
"0x4A,0x4B-FF",Unassigned,,,
|
||||
"0x4B-55,*",Unassigned,,,
|
||||
"0x56,0x00",TLS_FALLBACK_SCSV,Y,N,[RFC7507]
|
||||
"0x56,0x01-FF",Unassigned,,,
|
||||
"0x57-59,*",Unassigned,,,
|
||||
"0x5A,0x00-59",Unassigned,,,
|
||||
"0x5A,0x5A",Reserved,Y,N,[RFC8701]
|
||||
"0x5A,0x5B-FF",Unassigned,,,
|
||||
"0x5B-69,*",Unassigned,,,
|
||||
"0x6A,0x00-69",Unassigned,,,
|
||||
"0x6A,0x6A",Reserved,Y,N,[RFC8701]
|
||||
"0x6A,0x6B-FF",Unassigned,,,
|
||||
"0x6B-79,*",Unassigned,,,
|
||||
"0x7A,0x00-79",Unassigned,,,
|
||||
"0x7A,0x7A",Reserved,Y,N,[RFC8701]
|
||||
"0x7A,0x7B-FF",Unassigned,,,
|
||||
"0x7B-89,*",Unassigned,,,
|
||||
"0x8A,0x00-89",Unassigned,,,
|
||||
"0x8A,0x8A",Reserved,Y,N,[RFC8701]
|
||||
"0x8A,0x8B-FF",Unassigned,,,
|
||||
"0x8B-99,*",Unassigned,,,
|
||||
"0x9A,0x00-99",Unassigned,,,
|
||||
"0x9A,0x9A",Reserved,Y,N,[RFC8701]
|
||||
"0x9A,0x9B-FF",Unassigned,,,
|
||||
"0x9B-A9,*",Unassigned,,,
|
||||
"0xAA,0x00-A9",Unassigned,,,
|
||||
"0xAA,0xAA",Reserved,Y,N,[RFC8701]
|
||||
"0xAA,0xAB-FF",Unassigned,,,
|
||||
"0xAB-B9,*",Unassigned,,,
|
||||
"0xBA,0x00-B9",Unassigned,,,
|
||||
"0xBA,0xBA",Reserved,Y,N,[RFC8701]
|
||||
"0xBA,0xBB-FF",Unassigned,,,
|
||||
"0xBB-BF,*",Unassigned,,,
|
||||
"0xC0,0x00",Unassigned,,,
|
||||
"0xC0,0x01",TLS_ECDH_ECDSA_WITH_NULL_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x02",TLS_ECDH_ECDSA_WITH_RC4_128_SHA,N,N,[RFC8422][RFC6347]
|
||||
"0xC0,0x03",TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x04",TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x05",TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x06",TLS_ECDHE_ECDSA_WITH_NULL_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x07",TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,N,N,[RFC8422][RFC6347]
|
||||
"0xC0,0x08",TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x09",TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x0A",TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x0B",TLS_ECDH_RSA_WITH_NULL_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x0C",TLS_ECDH_RSA_WITH_RC4_128_SHA,N,N,[RFC8422][RFC6347]
|
||||
"0xC0,0x0D",TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x0E",TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x0F",TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x10",TLS_ECDHE_RSA_WITH_NULL_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x11",TLS_ECDHE_RSA_WITH_RC4_128_SHA,N,N,[RFC8422][RFC6347]
|
||||
"0xC0,0x12",TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x13",TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x14",TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x15",TLS_ECDH_anon_WITH_NULL_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x16",TLS_ECDH_anon_WITH_RC4_128_SHA,N,N,[RFC8422][RFC6347]
|
||||
"0xC0,0x17",TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x18",TLS_ECDH_anon_WITH_AES_128_CBC_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x19",TLS_ECDH_anon_WITH_AES_256_CBC_SHA,Y,N,[RFC8422]
|
||||
"0xC0,0x1A",TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5054]
|
||||
"0xC0,0x1B",TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5054]
|
||||
"0xC0,0x1C",TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5054]
|
||||
"0xC0,0x1D",TLS_SRP_SHA_WITH_AES_128_CBC_SHA,Y,N,[RFC5054]
|
||||
"0xC0,0x1E",TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,Y,N,[RFC5054]
|
||||
"0xC0,0x1F",TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,Y,N,[RFC5054]
|
||||
"0xC0,0x20",TLS_SRP_SHA_WITH_AES_256_CBC_SHA,Y,N,[RFC5054]
|
||||
"0xC0,0x21",TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,Y,N,[RFC5054]
|
||||
"0xC0,0x22",TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,Y,N,[RFC5054]
|
||||
"0xC0,0x23",TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,Y,N,[RFC5289]
|
||||
"0xC0,0x24",TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,Y,N,[RFC5289]
|
||||
"0xC0,0x25",TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,Y,N,[RFC5289]
|
||||
"0xC0,0x26",TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,Y,N,[RFC5289]
|
||||
"0xC0,0x27",TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,Y,N,[RFC5289]
|
||||
"0xC0,0x28",TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,Y,N,[RFC5289]
|
||||
"0xC0,0x29",TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,Y,N,[RFC5289]
|
||||
"0xC0,0x2A",TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,Y,N,[RFC5289]
|
||||
"0xC0,0x2B",TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,Y,Y,[RFC5289]
|
||||
"0xC0,0x2C",TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,Y,Y,[RFC5289]
|
||||
"0xC0,0x2D",TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,Y,N,[RFC5289]
|
||||
"0xC0,0x2E",TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,Y,N,[RFC5289]
|
||||
"0xC0,0x2F",TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,Y,Y,[RFC5289]
|
||||
"0xC0,0x30",TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,Y,Y,[RFC5289]
|
||||
"0xC0,0x31",TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,Y,N,[RFC5289]
|
||||
"0xC0,0x32",TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,Y,N,[RFC5289]
|
||||
"0xC0,0x33",TLS_ECDHE_PSK_WITH_RC4_128_SHA,N,N,[RFC5489][RFC6347]
|
||||
"0xC0,0x34",TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5489]
|
||||
"0xC0,0x35",TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,Y,N,[RFC5489]
|
||||
"0xC0,0x36",TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,Y,N,[RFC5489]
|
||||
"0xC0,0x37",TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,Y,N,[RFC5489]
|
||||
"0xC0,0x38",TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,Y,N,[RFC5489]
|
||||
"0xC0,0x39",TLS_ECDHE_PSK_WITH_NULL_SHA,Y,N,[RFC5489]
|
||||
"0xC0,0x3A",TLS_ECDHE_PSK_WITH_NULL_SHA256,Y,N,[RFC5489]
|
||||
"0xC0,0x3B",TLS_ECDHE_PSK_WITH_NULL_SHA384,Y,N,[RFC5489]
|
||||
"0xC0,0x3C",TLS_RSA_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x3D",TLS_RSA_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x3E",TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x3F",TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x40",TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x41",TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x42",TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x43",TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x44",TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x45",TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x46",TLS_DH_anon_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x47",TLS_DH_anon_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x48",TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x49",TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x4A",TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x4B",TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x4C",TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x4D",TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x4E",TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x4F",TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x50",TLS_RSA_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x51",TLS_RSA_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x52",TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x53",TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x54",TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x55",TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x56",TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x57",TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x58",TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x59",TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x5A",TLS_DH_anon_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x5B",TLS_DH_anon_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x5C",TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x5D",TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x5E",TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x5F",TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x60",TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x61",TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x62",TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x63",TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x64",TLS_PSK_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x65",TLS_PSK_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x66",TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x67",TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x68",TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x69",TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x6A",TLS_PSK_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x6B",TLS_PSK_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x6C",TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x6D",TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x6E",TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x6F",TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x70",TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
|
||||
"0xC0,0x71",TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
|
||||
"0xC0,0x72",TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x73",TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x74",TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x75",TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x76",TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x77",TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x78",TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x79",TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x7A",TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x7B",TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x7C",TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x7D",TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x7E",TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x7F",TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x80",TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x81",TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x82",TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x83",TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x84",TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x85",TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x86",TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x87",TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x88",TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x89",TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x8A",TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x8B",TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x8C",TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x8D",TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x8E",TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x8F",TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x90",TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x91",TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x92",TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x93",TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x94",TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x95",TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x96",TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x97",TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x98",TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x99",TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x9A",TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
|
||||
"0xC0,0x9B",TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
|
||||
"0xC0,0x9C",TLS_RSA_WITH_AES_128_CCM,Y,N,[RFC6655]
|
||||
"0xC0,0x9D",TLS_RSA_WITH_AES_256_CCM,Y,N,[RFC6655]
|
||||
"0xC0,0x9E",TLS_DHE_RSA_WITH_AES_128_CCM,Y,Y,[RFC6655]
|
||||
"0xC0,0x9F",TLS_DHE_RSA_WITH_AES_256_CCM,Y,Y,[RFC6655]
|
||||
"0xC0,0xA0",TLS_RSA_WITH_AES_128_CCM_8,Y,N,[RFC6655]
|
||||
"0xC0,0xA1",TLS_RSA_WITH_AES_256_CCM_8,Y,N,[RFC6655]
|
||||
"0xC0,0xA2",TLS_DHE_RSA_WITH_AES_128_CCM_8,Y,N,[RFC6655]
|
||||
"0xC0,0xA3",TLS_DHE_RSA_WITH_AES_256_CCM_8,N,N,[RFC6655]
|
||||
"0xC0,0xA4",TLS_PSK_WITH_AES_128_CCM,Y,N,[RFC6655]
|
||||
"0xC0,0xA5",TLS_PSK_WITH_AES_256_CCM,Y,N,[RFC6655]
|
||||
"0xC0,0xA6",TLS_DHE_PSK_WITH_AES_128_CCM,Y,Y,[RFC6655]
|
||||
"0xC0,0xA7",TLS_DHE_PSK_WITH_AES_256_CCM,Y,Y,[RFC6655]
|
||||
"0xC0,0xA8",TLS_PSK_WITH_AES_128_CCM_8,Y,N,[RFC6655]
|
||||
"0xC0,0xA9",TLS_PSK_WITH_AES_256_CCM_8,Y,N,[RFC6655]
|
||||
"0xC0,0xAA",TLS_PSK_DHE_WITH_AES_128_CCM_8,Y,N,[RFC6655]
|
||||
"0xC0,0xAB",TLS_PSK_DHE_WITH_AES_256_CCM_8,Y,N,[RFC6655]
|
||||
"0xC0,0xAC",TLS_ECDHE_ECDSA_WITH_AES_128_CCM,Y,N,[RFC7251]
|
||||
"0xC0,0xAD",TLS_ECDHE_ECDSA_WITH_AES_256_CCM,Y,N,[RFC7251]
|
||||
"0xC0,0xAE",TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,Y,N,[RFC7251]
|
||||
"0xC0,0xAF",TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,Y,N,[RFC7251]
|
||||
"0xC0,0xB0",TLS_ECCPWD_WITH_AES_128_GCM_SHA256,Y,N,[RFC8492]
|
||||
"0xC0,0xB1",TLS_ECCPWD_WITH_AES_256_GCM_SHA384,Y,N,[RFC8492]
|
||||
"0xC0,0xB2",TLS_ECCPWD_WITH_AES_128_CCM_SHA256,Y,N,[RFC8492]
|
||||
"0xC0,0xB3",TLS_ECCPWD_WITH_AES_256_CCM_SHA384,Y,N,[RFC8492]
|
||||
"0xC0,0xB4",TLS_SHA256_SHA256,Y,N,[RFC9150]
|
||||
"0xC0,0xB5",TLS_SHA384_SHA384,Y,N,[RFC9150]
|
||||
"0xC0,0xB6-FF",Unassigned,,,
|
||||
"0xC1,0x00",TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC,N,N,[RFC9189]
|
||||
"0xC1,0x01",TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC,N,N,[RFC9189]
|
||||
"0xC1,0x02",TLS_GOSTR341112_256_WITH_28147_CNT_IMIT,N,N,[RFC9189]
|
||||
"0xC1,0x03",TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_L,N,N,[RFC9367]
|
||||
"0xC1,0x04",TLS_GOSTR341112_256_WITH_MAGMA_MGM_L,N,N,[RFC9367]
|
||||
"0xC1,0x05",TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_S,N,N,[RFC9367]
|
||||
"0xC1,0x06",TLS_GOSTR341112_256_WITH_MAGMA_MGM_S,N,N,[RFC9367]
|
||||
"0xC1,0x07-FF",Unassigned,,,
|
||||
"0xC2-C9,*",Unassigned,,,
|
||||
"0xCA,0x00-C9",Unassigned,,,
|
||||
"0xCA,0xCA",Reserved,Y,N,[RFC8701]
|
||||
"0xCA,0xCB-FF",Unassigned,,,
|
||||
"0xCB,*",Unassigned,,,
|
||||
"0xCC,0x00-A7",Unassigned,,,
|
||||
"0xCC,0xA8",TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,Y,Y,[RFC7905]
|
||||
"0xCC,0xA9",TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,Y,Y,[RFC7905]
|
||||
"0xCC,0xAA",TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,Y,Y,[RFC7905]
|
||||
"0xCC,0xAB",TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,Y,N,[RFC7905]
|
||||
"0xCC,0xAC",TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,Y,Y,[RFC7905]
|
||||
"0xCC,0xAD",TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,Y,Y,[RFC7905]
|
||||
"0xCC,0xAE",TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,Y,N,[RFC7905]
|
||||
"0xCC,0xAF-FF",Unassigned,,,
|
||||
"0xCD-CF,*",Unassigned,,,
|
||||
"0xD0,0x00",Unassigned,,,
|
||||
"0xD0,0x01",TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256,Y,Y,[RFC8442]
|
||||
"0xD0,0x02",TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384,Y,Y,[RFC8442]
|
||||
"0xD0,0x03",TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256,Y,N,[RFC8442]
|
||||
"0xD0,0x04",Unassigned,,,
|
||||
"0xD0,0x05",TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256,Y,Y,[RFC8442]
|
||||
"0xD0,0x06-FF",Unassigned,,,
|
||||
"0xD1-D9,*",Unassigned,,,
|
||||
"0xDA,0x00-D9",Unassigned,,,
|
||||
"0xDA,0xDA",Reserved,Y,N,[RFC8701]
|
||||
"0xDA,0xDB-FF",Unassigned,,,
|
||||
"0xDB-E9,*",Unassigned,,,
|
||||
"0xEA,0x00-E9",Unassigned,,,
|
||||
"0xEA,0xEA",Reserved,Y,N,[RFC8701]
|
||||
"0xEA,0xEB-FF",Unassigned,,,
|
||||
"0xEB-F9,*",Unassigned,,,
|
||||
"0xFA,0x00-C9",Unassigned,,,
|
||||
"0xFA,0xFA",Reserved,Y,N,[RFC8701]
|
||||
"0xFA,0xFB-FF",Unassigned,,,
|
||||
"0xFB-FD,*",Unassigned,,,
|
||||
"0xFE,0x00-FD",Unassigned,,,
|
||||
"0xFE,0xFE-FF","Reserved to avoid conflicts with
|
||||
widely deployed implementations",,,[Pasi_Eronen]
|
||||
"0xFF,0x00-FF",Reserved for Private Use,,,[RFC8446]
|
|
|
@ -0,0 +1,110 @@
|
|||
// SPDX-FileCopyrightText: 2023 nervuri <https://nervuri.net/contact>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Inspired by Andrew Ayer's tlshacks:
|
||||
// https://github.com/AGWA/tlshacks/blob/main/generate_ciphersuites.go
|
||||
|
||||
package clienthello
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// https://www.iana.org/assignments/tls-parameters/tls-parameters-4.csv
|
||||
//
|
||||
//go:embed cipher-suites.csv
|
||||
var cipherSuitesCSV string
|
||||
|
||||
var CipherSuiteList = parseCipherSuitesCSV()
|
||||
|
||||
type CipherSuite any // (uint16 | CipherSuiteInfo)
|
||||
|
||||
type CipherSuiteInfo = struct {
|
||||
Code uint16 `json:"code"`
|
||||
HexCode string `json:"hex_code"`
|
||||
Name string `json:"name"`
|
||||
Recommended bool `json:"-"`
|
||||
Reference string `json:"-"`
|
||||
}
|
||||
|
||||
// TLS signaling cipher suite values
|
||||
const (
|
||||
scsvRenegotiation uint16 = 0x00ff
|
||||
)
|
||||
|
||||
func parseCipherSuitesCSV() map[uint16]CipherSuiteInfo {
|
||||
cipherSuites := map[uint16]CipherSuiteInfo{}
|
||||
r := csv.NewReader(strings.NewReader(cipherSuitesCSV))
|
||||
|
||||
// Skip CSV header.
|
||||
_, err := r.Read()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for {
|
||||
row, err := r.Read()
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
var (
|
||||
val = row[0]
|
||||
desc = row[1]
|
||||
rec = row[3]
|
||||
ref = row[4]
|
||||
)
|
||||
if desc == "Unassigned" {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(desc, "Reserved") && ref != "[RFC8701]" {
|
||||
continue
|
||||
}
|
||||
val = strings.Replace(val, ",", "", 1)
|
||||
val = strings.Replace(val, "0x", "", 2)
|
||||
code, err := strconv.ParseUint(val, 16, 16)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
suite := CipherSuiteInfo{
|
||||
Code: uint16(code),
|
||||
HexCode: val,
|
||||
Name: desc,
|
||||
Reference: ref,
|
||||
}
|
||||
if rec == "Y" {
|
||||
suite.Recommended = true
|
||||
}
|
||||
if ref == "[RFC8701]" {
|
||||
suite.Name = "GREASE"
|
||||
}
|
||||
|
||||
cipherSuites[suite.Code] = suite
|
||||
}
|
||||
return cipherSuites
|
||||
}
|
||||
|
||||
func GetCipherSuiteInfo(cipherSuiteCode uint16) CipherSuiteInfo {
|
||||
info, found := CipherSuiteList[cipherSuiteCode]
|
||||
if !found {
|
||||
info = CipherSuiteInfo{
|
||||
Code: cipherSuiteCode,
|
||||
HexCode: fmt.Sprintf("%04X", cipherSuiteCode),
|
||||
}
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func (m *ClientHelloMsg) AddCipherSuiteInfo() {
|
||||
for i, suite := range m.CipherSuites {
|
||||
m.CipherSuites[i] = GetCipherSuiteInfo(suite.(uint16))
|
||||
}
|
||||
}
|
|
@ -13,118 +13,13 @@ import (
|
|||
"crypto/md5"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"golang.org/x/crypto/cryptobyte"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// TLS versions
|
||||
const (
|
||||
versionSSL30 = 0x0300 // 768
|
||||
versionTLS10 = 0x0301 // 769
|
||||
versionTLS11 = 0x0302 // 770
|
||||
versionTLS12 = 0x0303 // 771
|
||||
versionTLS13 = 0x0304 // 772
|
||||
)
|
||||
|
||||
// TLS compression types
|
||||
const (
|
||||
compressionNone uint8 = 0
|
||||
)
|
||||
|
||||
// TLS extension numbers
|
||||
const (
|
||||
extensionServerName uint16 = 0
|
||||
extensionStatusRequest uint16 = 5
|
||||
extensionSupportedGroups uint16 = 10 // elliptic_curves in TLS versions prior to 1.3, see RFC 8446, Section 4.2.7
|
||||
extensionSupportedPointFormats uint16 = 11
|
||||
extensionSignatureAlgorithms uint16 = 13
|
||||
extensionALPN uint16 = 16
|
||||
extensionSCT uint16 = 18
|
||||
extensionPadding uint16 = 21
|
||||
extensionEncryptThenMac uint16 = 22
|
||||
extensionExtendedMasterSecret uint16 = 23
|
||||
extensionCompressCertificate uint16 = 27
|
||||
extensionSessionTicket uint16 = 35
|
||||
extensionPreSharedKey uint16 = 41
|
||||
extensionEarlyData uint16 = 42
|
||||
extensionSupportedVersions uint16 = 43
|
||||
extensionCookie uint16 = 44
|
||||
extensionPSKModes uint16 = 45
|
||||
extensionCertificateAuthorities uint16 = 47
|
||||
extensionPostHandshakeAuth uint16 = 49
|
||||
extensionSignatureAlgorithmsCert uint16 = 50
|
||||
extensionKeyShare uint16 = 51
|
||||
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
|
||||
extensionApplicationSettings uint16 = 17513 // not IANA assigned
|
||||
extensionRenegotiationInfo uint16 = 0xff01
|
||||
)
|
||||
|
||||
// TLS signaling cipher suite values
|
||||
const (
|
||||
scsvRenegotiation uint16 = 0x00ff
|
||||
)
|
||||
|
||||
// TLS CertificateStatusType (RFC 3546)
|
||||
const (
|
||||
statusTypeOCSP uint8 = 1
|
||||
)
|
||||
|
||||
// curveID is the type of a TLS identifier for an elliptic curve. See
|
||||
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8.
|
||||
//
|
||||
// In TLS 1.3, this type is called NamedGroup, but at this time this library
|
||||
// only supports Elliptic Curve based groups. See RFC 8446, Section 4.2.7.
|
||||
type curveID uint16
|
||||
|
||||
const (
|
||||
curveP256 curveID = 23
|
||||
curveP384 curveID = 24
|
||||
curveP521 curveID = 25
|
||||
x25519 curveID = 29
|
||||
)
|
||||
|
||||
// TLS 1.3 Key Share. See RFC 8446, Section 4.2.8.
|
||||
type keyShare struct {
|
||||
Group curveID `json:"group"`
|
||||
Data byteSlice `json:"data"`
|
||||
}
|
||||
|
||||
// TLS 1.3 PSK Identity. Can be a Session Ticket, or a reference to a saved
|
||||
// session. See RFC 8446, Section 4.2.11.
|
||||
type pskIdentity struct {
|
||||
Identity byteSlice `json:"identity"`
|
||||
ObfuscatedTicketAge uint32 `json:"obfuscated_ticket_age"`
|
||||
}
|
||||
|
||||
// signatureScheme identifies a signature algorithm supported by TLS. See
|
||||
// RFC 8446, Section 4.2.3.
|
||||
type signatureScheme uint16
|
||||
|
||||
const (
|
||||
// RSASSA-PKCS1-v1_5 algorithms.
|
||||
PKCS1WithSHA256 signatureScheme = 0x0401
|
||||
PKCS1WithSHA384 signatureScheme = 0x0501
|
||||
PKCS1WithSHA512 signatureScheme = 0x0601
|
||||
|
||||
// RSASSA-PSS algorithms with public key OID rsaEncryption.
|
||||
PSSWithSHA256 signatureScheme = 0x0804
|
||||
PSSWithSHA384 signatureScheme = 0x0805
|
||||
PSSWithSHA512 signatureScheme = 0x0806
|
||||
|
||||
// ECDSA algorithms. Only constrained to a specific curve in TLS 1.3.
|
||||
ECDSAWithP256AndSHA256 signatureScheme = 0x0403
|
||||
ECDSAWithP384AndSHA384 signatureScheme = 0x0503
|
||||
ECDSAWithP521AndSHA512 signatureScheme = 0x0603
|
||||
|
||||
// Legacy signature and hash algorithms for TLS 1.2.
|
||||
PKCS1WithSHA1 signatureScheme = 0x0201
|
||||
ECDSAWithSHA1 signatureScheme = 0x0203
|
||||
)
|
||||
|
||||
// Check if this is a GREASE value (RFC 8701)
|
||||
// Check if this is a GREASE value (RFC 8701).
|
||||
func isGREASE(value uint16) bool {
|
||||
// Values for: cipher suites, ALPN,
|
||||
// extensions, named groups, signature algorithms and TLS versions:
|
||||
|
@ -132,10 +27,6 @@ func isGREASE(value uint16) bool {
|
|||
0x0a0a, 0x1a1a, 0x2a2a, 0x3a3a, 0x4a4a, 0x5a5a, 0x6a6a, 0x7a7a,
|
||||
0x8a8a, 0x9a9a, 0xaaaa, 0xbaba, 0xcaca, 0xdada, 0xeaea, 0xfafa,
|
||||
}
|
||||
// Values for PSK key exchange modes:
|
||||
//greasePSKModes := [8]uint8{
|
||||
// 0x0b, 0x2a, 0x49, 0x68, 0x87, 0xa6, 0xc5, 0xe4,
|
||||
//}
|
||||
// Run the check
|
||||
for _, greaseValue := range greaseValues {
|
||||
if value == greaseValue {
|
||||
|
@ -164,47 +55,12 @@ func (bs byteSlice) MarshalText() ([]byte, error) {
|
|||
return []byte(hex.EncodeToString(bs)), nil
|
||||
}
|
||||
|
||||
type uint8Slice []uint8
|
||||
|
||||
func (numbers uint8Slice) MarshalJSON() ([]byte, error) {
|
||||
// Used in json.Marshal() to convert []uint8 to array.
|
||||
newSlice := make([]uint, len(numbers))
|
||||
for i, n := range numbers {
|
||||
newSlice[i] = uint(n)
|
||||
}
|
||||
return json.Marshal(newSlice)
|
||||
}
|
||||
|
||||
type extensionData struct {
|
||||
Raw byteSlice `json:"raw"`
|
||||
ServerName string `json:"server_name,omitempty"`
|
||||
StatusType uint8 `json:"status_type,omitempty"`
|
||||
SupportedGroups []curveID `json:"supported_groups,omitempty"`
|
||||
SupportedPointFormats uint8Slice `json:"supported_point_formats,omitempty"`
|
||||
SupportedSignatureAlgorithms []signatureScheme `json:"supported_signature_algorithms,omitempty"`
|
||||
RenegotiationInfo []byte `json:"renegotiation_info,omitempty"`
|
||||
AlpnProtocols []string `json:"alpn_protocols,omitempty"`
|
||||
SupportedVersions []uint16 `json:"supported_tls_versions,omitempty"`
|
||||
Cookie byteSlice `json:"cookie,omitempty"`
|
||||
KeyShares []keyShare `json:"key_shares,omitempty"`
|
||||
PskModes uint8Slice `json:"psk_modes,omitempty"`
|
||||
PskIdentities []pskIdentity `json:"psk_identities,omitempty"`
|
||||
PskBinders []byteSlice `json:"psk_binders,omitempty"`
|
||||
Length uint16 `json:"length,omitempty"` // padding
|
||||
}
|
||||
|
||||
type extension struct {
|
||||
Code uint16 `json:"code"`
|
||||
Name string `json:"name"`
|
||||
Data extensionData `json:"data"`
|
||||
}
|
||||
|
||||
type highlights struct {
|
||||
//SupportedTLSVersions []uint16
|
||||
GmtUnixTime uint32 `json:"gmt_unix_time"` // first 4 bytes of client random
|
||||
GMTUnixTime uint32 `json:"gmt_unix_time"` // first 4 bytes of client random
|
||||
SecureRenegotiationSupport bool `json:"secure_renegotiation_support"`
|
||||
OcspStaplingSupport bool `json:"ocsp_stapling_support"`
|
||||
SctSupport bool `json:"sct_support"`
|
||||
OCSPStaplingSupport bool `json:"ocsp_stapling_support"`
|
||||
SCTSupport bool `json:"sct_support"`
|
||||
// Go's crypto/tls server does not support early data.
|
||||
EarlyData bool `json:"-"` // don't include in JSON
|
||||
JA3 string `json:"ja3"`
|
||||
|
@ -212,39 +68,43 @@ type highlights struct {
|
|||
}
|
||||
|
||||
type ClientHelloMsg struct {
|
||||
Raw byteSlice `json:"raw"`
|
||||
RecordHeaderTLSVersion uint16 `json:"record_header_tls_version"` // TLSv1.0 (769)
|
||||
TLSVersion uint16 `json:"client_tls_version"` // TLSv1.2 (771)
|
||||
Random byteSlice `json:"random"`
|
||||
SessionID byteSlice `json:"session_id"`
|
||||
CipherSuites []uint16 `json:"cipher_suites"`
|
||||
CompressionMethods uint8Slice `json:"compression_methods"`
|
||||
Extensions []extension `json:"extensions"`
|
||||
Highlights highlights `json:"highlights"`
|
||||
Raw byteSlice `json:"raw"`
|
||||
RecordHeaderTLSVersion TLSVersion `json:"record_header_tls_version"` // TLSv1.0 (769)
|
||||
TLSVersion TLSVersion `json:"client_tls_version"` // TLSv1.2 (771)
|
||||
Random byteSlice `json:"random"`
|
||||
SessionID byteSlice `json:"session_id"`
|
||||
CipherSuites []CipherSuite `json:"cipher_suites"`
|
||||
CompressionMethods []CompressionMethod `json:"compression_methods"`
|
||||
Extensions []Extension `json:"extensions"`
|
||||
Highlights highlights `json:"highlights"`
|
||||
}
|
||||
|
||||
func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
||||
*m = ClientHelloMsg{Raw: data}
|
||||
s := cryptobyte.String(data)
|
||||
|
||||
var recordHeaderTLSVersion uint16
|
||||
var tlsVersion uint16
|
||||
var random []byte
|
||||
var sessionID []byte
|
||||
if !s.Skip(1) || !s.ReadUint16(&m.RecordHeaderTLSVersion) || !s.Skip(2) ||
|
||||
if !s.Skip(1) || !s.ReadUint16(&recordHeaderTLSVersion) || !s.Skip(2) ||
|
||||
!s.Skip(4) || // message type and uint24 length field
|
||||
!s.ReadUint16(&m.TLSVersion) || !s.ReadBytes(&random, 32) ||
|
||||
!s.ReadUint16(&tlsVersion) || !s.ReadBytes(&random, 32) ||
|
||||
!readUint8LengthPrefixed(&s, &sessionID) {
|
||||
return false
|
||||
}
|
||||
m.RecordHeaderTLSVersion = recordHeaderTLSVersion
|
||||
m.TLSVersion = tlsVersion
|
||||
m.Random = random
|
||||
m.Highlights.GmtUnixTime = binary.BigEndian.Uint32(random[0:4])
|
||||
m.Highlights.GMTUnixTime = binary.BigEndian.Uint32(random[0:4])
|
||||
|
||||
m.SessionID = sessionID
|
||||
|
||||
m.CipherSuites = []CipherSuite{}
|
||||
var cipherSuites cryptobyte.String
|
||||
if !s.ReadUint16LengthPrefixed(&cipherSuites) {
|
||||
return false
|
||||
}
|
||||
m.CipherSuites = []uint16{}
|
||||
m.Highlights.SecureRenegotiationSupport = false
|
||||
for !cipherSuites.Empty() {
|
||||
var suite uint16
|
||||
|
@ -261,7 +121,9 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
if !readUint8LengthPrefixed(&s, &compressionMethods) {
|
||||
return false
|
||||
}
|
||||
m.CompressionMethods = compressionMethods
|
||||
for _, cm := range compressionMethods {
|
||||
m.CompressionMethods = append(m.CompressionMethods, cm)
|
||||
}
|
||||
|
||||
if s.Empty() {
|
||||
// ClientHello is optionally followed by extension data
|
||||
|
@ -274,19 +136,19 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
}
|
||||
|
||||
for !extensions.Empty() {
|
||||
var extension extension
|
||||
var extCode uint16
|
||||
var extData cryptobyte.String
|
||||
if !extensions.ReadUint16(&extension.Code) ||
|
||||
if !extensions.ReadUint16(&extCode) ||
|
||||
!extensions.ReadUint16LengthPrefixed(&extData) {
|
||||
return false
|
||||
}
|
||||
|
||||
var extension = GetExtensionInfo(extCode)
|
||||
extension.Data.Raw = []byte(extData)
|
||||
|
||||
switch extension.Code {
|
||||
case extensionServerName:
|
||||
// Server Name Indication
|
||||
// RFC 6066, Section 3
|
||||
extension.Name = "server_name" // Server Name Indication
|
||||
var nameList cryptobyte.String
|
||||
if !extData.ReadUint16LengthPrefixed(&nameList) || nameList.Empty() {
|
||||
return false
|
||||
|
@ -314,50 +176,55 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
}
|
||||
}
|
||||
case extensionNextProtoNeg:
|
||||
// draft-agl-tls-nextprotoneg-04
|
||||
extension.Name = "next_protocol_negotiation" // Next Protocol Negotiation
|
||||
// Next Protocol Negotiation
|
||||
// draft-agl-tls-nextprotoneg-04 (not IANA assiged)
|
||||
extension.Name = "next_protocol_negotiation"
|
||||
case extensionStatusRequest:
|
||||
// Certificate Status Request
|
||||
// RFC 4366, Section 3.6
|
||||
extension.Name = "status_request" // Certificate Status Request
|
||||
var ignored cryptobyte.String
|
||||
if !extData.ReadUint8(&extension.Data.StatusType) ||
|
||||
!extData.ReadUint16LengthPrefixed(&ignored) || // responder_id_list
|
||||
!extData.ReadUint16LengthPrefixed(&ignored) { // request_extensions
|
||||
return false
|
||||
}
|
||||
m.Highlights.OcspStaplingSupport = extension.Data.StatusType == statusTypeOCSP
|
||||
m.Highlights.OCSPStaplingSupport = extension.Data.StatusType == statusTypeOCSP
|
||||
case extensionSupportedGroups:
|
||||
// Supported Groups (former name: elliptic_curves)
|
||||
// RFC 4492, sections 5.1.1 and RFC 8446, Section 4.2.7
|
||||
extension.Name = "supported_groups" // Supported Groups
|
||||
//extension.Name = "elliptic_curves" // old name
|
||||
var curves cryptobyte.String
|
||||
if !extData.ReadUint16LengthPrefixed(&curves) || curves.Empty() {
|
||||
var groups cryptobyte.String
|
||||
if !extData.ReadUint16LengthPrefixed(&groups) || groups.Empty() {
|
||||
return false
|
||||
}
|
||||
extension.Data.SupportedGroups = make([]curveID, 0)
|
||||
for !curves.Empty() {
|
||||
var curve uint16
|
||||
if !curves.ReadUint16(&curve) {
|
||||
extension.Data.SupportedGroups = make([]NamedGroup, 0)
|
||||
for !groups.Empty() {
|
||||
var group uint16
|
||||
if !groups.ReadUint16(&group) {
|
||||
return false
|
||||
}
|
||||
extension.Data.SupportedGroups = append(
|
||||
extension.Data.SupportedGroups, curveID(curve))
|
||||
extension.Data.SupportedGroups, group)
|
||||
}
|
||||
case extensionSupportedPointFormats:
|
||||
// Supported Point Formats
|
||||
// RFC 4492, Section 5.1.2
|
||||
extension.Name = "ec_point_formats" // Supported Point Formats
|
||||
var supportedPointFormats []uint8
|
||||
if !readUint8LengthPrefixed(&extData, &supportedPointFormats) ||
|
||||
len(supportedPointFormats) == 0 {
|
||||
return false
|
||||
}
|
||||
extension.Data.SupportedPointFormats = supportedPointFormats
|
||||
extension.Data.SupportedPointFormats = make(
|
||||
[]ECPointFormat, len(supportedPointFormats))
|
||||
for i, pointFormatCode := range supportedPointFormats {
|
||||
extension.Data.SupportedPointFormats[i] = pointFormatCode
|
||||
}
|
||||
case extensionSessionTicket:
|
||||
// Session Ticket
|
||||
// RFC 5077, Section 3.2
|
||||
extension.Name = "session_ticket" // Session Ticket
|
||||
case extensionSignatureAlgorithms:
|
||||
// Signature Algorithms
|
||||
// RFC 5246, Section 7.4.1.4.1
|
||||
extension.Name = "signature_algorithms" // Signature Algorithms
|
||||
extension.Data.SupportedSignatureAlgorithms = []SignatureScheme{}
|
||||
var sigAndAlgs cryptobyte.String
|
||||
if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() {
|
||||
return false
|
||||
|
@ -368,12 +235,12 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
return false
|
||||
}
|
||||
extension.Data.SupportedSignatureAlgorithms = append(
|
||||
extension.Data.SupportedSignatureAlgorithms,
|
||||
signatureScheme(sigAndAlg))
|
||||
extension.Data.SupportedSignatureAlgorithms, sigAndAlg)
|
||||
}
|
||||
case extensionSignatureAlgorithmsCert:
|
||||
// Signature Algorithms Cert
|
||||
// RFC 8446, Section 4.2.3
|
||||
extension.Name = "signature_algorithms_cert" // Signature Algorithms Cert
|
||||
extension.Data.SupportedSignatureAlgorithms = []SignatureScheme{}
|
||||
var sigAndAlgs cryptobyte.String
|
||||
if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() {
|
||||
return false
|
||||
|
@ -384,12 +251,11 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
return false
|
||||
}
|
||||
extension.Data.SupportedSignatureAlgorithms = append(
|
||||
extension.Data.SupportedSignatureAlgorithms,
|
||||
signatureScheme(sigAndAlg))
|
||||
extension.Data.SupportedSignatureAlgorithms, sigAndAlg)
|
||||
}
|
||||
case extensionRenegotiationInfo:
|
||||
// Renegotiation Indication
|
||||
// RFC 5746, Section 3.2
|
||||
extension.Name = "renegotiation_info" // Renegotiation Indication
|
||||
if !readUint8LengthPrefixed(
|
||||
&extData,
|
||||
&extension.Data.RenegotiationInfo) {
|
||||
|
@ -397,8 +263,8 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
}
|
||||
m.Highlights.SecureRenegotiationSupport = true
|
||||
case extensionALPN:
|
||||
// Application-Layer Protocol Negotiation
|
||||
// RFC 7301, Section 3.1
|
||||
extension.Name = "application_layer_protocol_negotiation" // Application-Layer Protocol Negotiation
|
||||
var protoList cryptobyte.String
|
||||
if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() {
|
||||
return false
|
||||
|
@ -408,16 +274,18 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
if !protoList.ReadUint8LengthPrefixed(&proto) || proto.Empty() {
|
||||
return false
|
||||
}
|
||||
extension.Data.AlpnProtocols = append(extension.Data.AlpnProtocols, string(proto))
|
||||
extension.Data.ALPNProtocols = append(
|
||||
extension.Data.ALPNProtocols, string(proto))
|
||||
}
|
||||
case extensionSCT:
|
||||
// Signed Certificate Timestamp
|
||||
// RFC 6962, Section 3.3.1
|
||||
extension.Name = "signed_certificate_timestamp" // Signed Certificate Timestamp
|
||||
m.Highlights.SctSupport = true
|
||||
m.Highlights.SCTSupport = true
|
||||
case extensionSupportedVersions:
|
||||
// Supported Versions
|
||||
// RFC 8446, Section 4.2.1
|
||||
extension.Name = "supported_versions" // Supported Versions
|
||||
var versList cryptobyte.String
|
||||
extension.Data.SupportedVersions = []TLSVersion{}
|
||||
if !extData.ReadUint8LengthPrefixed(&versList) || versList.Empty() {
|
||||
return false
|
||||
}
|
||||
|
@ -426,11 +294,12 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
if !versList.ReadUint16(&vers) {
|
||||
return false
|
||||
}
|
||||
extension.Data.SupportedVersions = append(extension.Data.SupportedVersions, vers)
|
||||
extension.Data.SupportedVersions = append(
|
||||
extension.Data.SupportedVersions, vers)
|
||||
}
|
||||
case extensionCookie:
|
||||
// Cookie
|
||||
// RFC 8446, Section 4.2.2
|
||||
extension.Name = "cookie" // Cookie
|
||||
var cookie []byte
|
||||
if !readUint16LengthPrefixed(&extData, &cookie) ||
|
||||
len(extension.Data.Cookie) == 0 {
|
||||
|
@ -438,38 +307,42 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
}
|
||||
extension.Data.Cookie = cookie
|
||||
case extensionKeyShare:
|
||||
// Key Share
|
||||
// RFC 8446, Section 4.2.8
|
||||
extension.Name = "key_share" // Key Share
|
||||
var clientShares cryptobyte.String
|
||||
if !extData.ReadUint16LengthPrefixed(&clientShares) {
|
||||
return false
|
||||
}
|
||||
for !clientShares.Empty() {
|
||||
var ks keyShare
|
||||
var ks KeyShare
|
||||
var ksGroup uint16
|
||||
var ksData []byte
|
||||
if !clientShares.ReadUint16((*uint16)(&ks.Group)) ||
|
||||
if !clientShares.ReadUint16(&ksGroup) ||
|
||||
!readUint16LengthPrefixed(&clientShares, &ksData) ||
|
||||
len(ksData) == 0 {
|
||||
return false
|
||||
}
|
||||
ks.Group = ksGroup
|
||||
ks.Data = ksData
|
||||
extension.Data.KeyShares = append(extension.Data.KeyShares, ks)
|
||||
}
|
||||
case extensionEarlyData:
|
||||
// Early Data Indication
|
||||
// RFC 8446, Section 4.2.10
|
||||
extension.Name = "early_data" // Early Data Indication
|
||||
m.Highlights.EarlyData = true
|
||||
case extensionPSKModes:
|
||||
// Pre-Shared Key Exchange Modes
|
||||
// RFC 8446, Section 4.2.9
|
||||
extension.Name = "psk_key_exchange_modes" // Pre-Shared Key Exchange Modes
|
||||
var pskModes []uint8
|
||||
if !readUint8LengthPrefixed(&extData, &pskModes) {
|
||||
return false
|
||||
}
|
||||
extension.Data.PskModes = pskModes
|
||||
for _, pskMode := range pskModes {
|
||||
extension.Data.PSKModes = append(extension.Data.PSKModes, pskMode)
|
||||
}
|
||||
case extensionPreSharedKey:
|
||||
// Pre-Shared Key
|
||||
// RFC 8446, Section 4.2.11
|
||||
extension.Name = "pre_shared_key" // Pre-Shared Key
|
||||
if !extensions.Empty() {
|
||||
return false // pre_shared_key must be the last extension
|
||||
}
|
||||
|
@ -478,7 +351,7 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
return false
|
||||
}
|
||||
for !identities.Empty() {
|
||||
var psk pskIdentity
|
||||
var psk PSKIdentity
|
||||
var identity []byte
|
||||
if !readUint16LengthPrefixed(&identities, &identity) ||
|
||||
!identities.ReadUint32(&psk.ObfuscatedTicketAge) ||
|
||||
|
@ -486,7 +359,7 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
return false
|
||||
}
|
||||
psk.Identity = identity
|
||||
extension.Data.PskIdentities = append(extension.Data.PskIdentities, psk)
|
||||
extension.Data.PSKIdentities = append(extension.Data.PSKIdentities, psk)
|
||||
}
|
||||
var binders cryptobyte.String
|
||||
if !extData.ReadUint16LengthPrefixed(&binders) || binders.Empty() {
|
||||
|
@ -498,41 +371,29 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
len(binder) == 0 {
|
||||
return false
|
||||
}
|
||||
extension.Data.PskBinders = append(extension.Data.PskBinders, binder)
|
||||
extension.Data.PSKBinders = append(extension.Data.PSKBinders, binder)
|
||||
}
|
||||
case extensionPadding:
|
||||
// Padding
|
||||
// RFC 7685
|
||||
extension.Name = "padding" // Padding
|
||||
extension.Data.Length = uint16(len(extData))
|
||||
case extensionEncryptThenMac:
|
||||
// RFC 7366
|
||||
extension.Name = "encrypt_then_mac" // Encrypt-then-MAC"
|
||||
case extensionExtendedMasterSecret:
|
||||
// RFC 7627
|
||||
extension.Name = "extended_master_secret" // Extended Master Secret
|
||||
case extensionPostHandshakeAuth:
|
||||
// RFC 8446, Section 4.2.6
|
||||
extension.Name = "post_handshake_auth" // Post-Handshake Client Authentication
|
||||
case extensionCompressCertificate:
|
||||
// Certificate Compression
|
||||
// RFC 8879
|
||||
extension.Name = "compress_certificate" // Certificate Compression
|
||||
// TODO: parse - https://www.rfc-editor.org/rfc/rfc8879.html
|
||||
case extensionApplicationSettings:
|
||||
// draft-vvv-tls-alps
|
||||
// Application-Layer Protocol Settings
|
||||
// draft-vvv-tls-alps (not IANA assiged)
|
||||
extension.Name = " application_settings"
|
||||
// TODO: parse - https://datatracker.ietf.org/doc/html/draft-vvv-tls-alps
|
||||
default:
|
||||
// Check if this is a GREASE extension (RFC 8701)
|
||||
if isGREASE(extension.Code) {
|
||||
extension.Name = "GREASE"
|
||||
} else {
|
||||
log.Println("Unknown extension:", extension.Code)
|
||||
}
|
||||
}
|
||||
|
||||
m.Extensions = append(m.Extensions, extension)
|
||||
|
||||
if extension.Name == "" {
|
||||
log.Println("Unknown extension:", extension.Code)
|
||||
}
|
||||
|
||||
if !extData.Empty() &&
|
||||
extension.Name != "GREASE" &&
|
||||
extension.Code != extensionPadding {
|
||||
|
@ -542,13 +403,13 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
|
||||
// JA3
|
||||
var ja3 strings.Builder
|
||||
var supportedGroups []curveID
|
||||
var supportedPointFormats uint8Slice
|
||||
ja3.WriteString(strconv.FormatUint(uint64(m.TLSVersion), 10) + ",")
|
||||
var supportedGroups []NamedGroup
|
||||
var supportedPointFormats []ECPointFormat
|
||||
ja3.WriteString(strconv.FormatUint(uint64(m.TLSVersion.(uint16)), 10) + ",")
|
||||
for i, cs := range m.CipherSuites {
|
||||
if !isGREASE(cs) { // ignore GREASE values
|
||||
ja3.WriteString(strconv.FormatUint(uint64(cs), 10))
|
||||
if i+1 != len(m.CipherSuites) {
|
||||
if !isGREASE(cs.(uint16)) { // ignore GREASE values
|
||||
ja3.WriteString(strconv.FormatUint(uint64(cs.(uint16)), 10))
|
||||
if i+1 != len(m.CipherSuites) { // if not last element, add "-"
|
||||
ja3.WriteString("-")
|
||||
}
|
||||
}
|
||||
|
@ -557,7 +418,7 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
for i, e := range m.Extensions {
|
||||
if !isGREASE(e.Code) { // ignore GREASE values
|
||||
ja3.WriteString(strconv.FormatUint(uint64(e.Code), 10))
|
||||
if i+1 != len(m.Extensions) {
|
||||
if i+1 != len(m.Extensions) { // if not last element, add "-"
|
||||
ja3.WriteString("-")
|
||||
}
|
||||
if e.Code == extensionSupportedGroups {
|
||||
|
@ -569,20 +430,18 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
}
|
||||
ja3.WriteString(",")
|
||||
for i, g := range supportedGroups {
|
||||
if !isGREASE(uint16(g)) { // ignore GREASE values
|
||||
ja3.WriteString(strconv.FormatUint(uint64(g), 10))
|
||||
if i+1 != len(supportedGroups) {
|
||||
if !isGREASE(g.(uint16)) { // ignore GREASE values
|
||||
ja3.WriteString(strconv.FormatUint(uint64(g.(uint16)), 10))
|
||||
if i+1 != len(supportedGroups) { // if not last element, add "-"
|
||||
ja3.WriteString("-")
|
||||
}
|
||||
}
|
||||
}
|
||||
ja3.WriteString(",")
|
||||
for i, pf := range supportedPointFormats {
|
||||
if !isGREASE(uint16(pf)) { // ignore GREASE values
|
||||
ja3.WriteString(strconv.FormatUint(uint64(pf), 10))
|
||||
if i+1 != len(supportedPointFormats) {
|
||||
ja3.WriteString("-")
|
||||
}
|
||||
ja3.WriteString(strconv.FormatUint(uint64(pf.(uint8)), 10))
|
||||
if i+1 != len(supportedPointFormats) { // if not last element, add "-"
|
||||
ja3.WriteString("-")
|
||||
}
|
||||
}
|
||||
m.Highlights.JA3 = ja3.String()
|
||||
|
@ -591,3 +450,14 @@ func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
|
|||
|
||||
return true
|
||||
}
|
||||
|
||||
// Add information about TLS versions, cipher suites, etc.
|
||||
func (m *ClientHelloMsg) AddInfo() {
|
||||
m.AddTLSVersionInfo()
|
||||
m.AddCipherSuiteInfo()
|
||||
m.AddSignatureSchemeInfo()
|
||||
m.AddNamedGroupInfo() // supported_groups
|
||||
m.AddECPointFormatInfo()
|
||||
m.AddCompressionMethodInfo()
|
||||
m.AddPSKModeInfo()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package clienthello
|
||||
|
||||
// https://www.rfc-editor.org/rfc/rfc3749#section-2
|
||||
var CompressionMethodList = map[uint8]CompressionMethodInfo{
|
||||
0: {Code: 0, Name: "null"},
|
||||
1: {Code: 1, Name: "DEFLATE"},
|
||||
}
|
||||
|
||||
type CompressionMethod any // (uint8 | CompressionMethodInfo)
|
||||
|
||||
type CompressionMethodInfo struct {
|
||||
Code uint8 `json:"code"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func GetCompressionMethodInfo(compressionMethodCode uint8) CompressionMethodInfo {
|
||||
info, found := CompressionMethodList[compressionMethodCode]
|
||||
if !found {
|
||||
info = CompressionMethodInfo{
|
||||
Code: compressionMethodCode,
|
||||
}
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func (m *ClientHelloMsg) AddCompressionMethodInfo() {
|
||||
for i, code := range m.CompressionMethods {
|
||||
m.CompressionMethods[i] = GetCompressionMethodInfo(code.(uint8))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
Value,Extension Name,TLS 1.3,DTLS-Only,Recommended,Reference
|
||||
0,server_name,"CH, EE, CR",N,Y,[RFC6066][RFC9261]
|
||||
1,max_fragment_length,"CH, EE",N,N,[RFC6066][RFC8449]
|
||||
2,client_certificate_url,-,N,Y,[RFC6066]
|
||||
3,trusted_ca_keys,-,N,Y,[RFC6066]
|
||||
4,truncated_hmac,-,N,N,[RFC6066][IESG Action 2018-08-16]
|
||||
5,status_request,"CH, CR, CT",N,Y,[RFC6066]
|
||||
6,user_mapping,-,N,Y,[RFC4681]
|
||||
7,client_authz,-,N,N,[RFC5878]
|
||||
8,server_authz,-,N,N,[RFC5878]
|
||||
9,cert_type,-,N,N,[RFC6091]
|
||||
10,"supported_groups (renamed from ""elliptic_curves"")","CH, EE",N,Y,[RFC8422][RFC7919]
|
||||
11,ec_point_formats,-,N,Y,[RFC8422]
|
||||
12,srp,-,N,N,[RFC5054]
|
||||
13,signature_algorithms,"CH, CR",N,Y,[RFC8446]
|
||||
14,use_srtp,"CH, EE",N,Y,[RFC5764]
|
||||
15,heartbeat,"CH, EE",N,Y,[RFC6520]
|
||||
16,application_layer_protocol_negotiation,"CH, EE",N,Y,[RFC7301]
|
||||
17,status_request_v2,-,N,Y,[RFC6961]
|
||||
18,signed_certificate_timestamp,"CH, CR, CT",N,N,[RFC6962]
|
||||
19,client_certificate_type,"CH, EE",N,Y,[RFC7250]
|
||||
20,server_certificate_type,"CH, EE",N,Y,[RFC7250]
|
||||
21,padding,CH,N,Y,[RFC7685]
|
||||
22,encrypt_then_mac,-,N,Y,[RFC7366]
|
||||
23,extended_master_secret,-,N,Y,[RFC7627]
|
||||
24,token_binding,-,N,Y,[RFC8472]
|
||||
25,cached_info,-,N,Y,[RFC7924]
|
||||
26,tls_lts,-,N,N,[draft-gutmann-tls-lts]
|
||||
27,compress_certificate,"CH, CR",N,Y,[RFC8879]
|
||||
28,record_size_limit,"CH, EE",N,Y,[RFC8449]
|
||||
29,pwd_protect,CH,N,N,[RFC8492]
|
||||
30,pwd_clear,CH,N,N,[RFC8492]
|
||||
31,password_salt,"CH, SH, HRR",N,N,[RFC8492]
|
||||
32,ticket_pinning,"CH, EE",N,N,[RFC8672]
|
||||
33,tls_cert_with_extern_psk,"CH, SH",N,N,[RFC8773]
|
||||
34,delegated_credential,"CH, CR, CT",N,Y,[RFC-ietf-tls-subcerts-15]
|
||||
35,"session_ticket (renamed from ""SessionTicket TLS"")",-,N,Y,[RFC5077][RFC8447]
|
||||
36,TLMSP,-,N,N,[ETSI TS 103 523-2]
|
||||
37,TLMSP_proxying,-,N,N,[ETSI TS 103 523-2]
|
||||
38,TLMSP_delegate,-,N,N,[ETSI TS 103 523-2]
|
||||
39,supported_ekt_ciphers,"CH, EE",N,Y,[RFC8870]
|
||||
40,Reserved,,,,[tls-reg-review mailing list]
|
||||
41,pre_shared_key,"CH, SH",N,Y,[RFC8446]
|
||||
42,early_data,"CH, EE, NST",N,Y,[RFC8446]
|
||||
43,supported_versions,"CH, SH, HRR",N,Y,[RFC8446]
|
||||
44,cookie,"CH, HRR",N,Y,[RFC8446]
|
||||
45,psk_key_exchange_modes,CH,N,Y,[RFC8446]
|
||||
46,Reserved,,,,[tls-reg-review mailing list]
|
||||
47,certificate_authorities,"CH, CR",N,Y,[RFC8446]
|
||||
48,oid_filters,CR,N,Y,[RFC8446]
|
||||
49,post_handshake_auth,CH,N,Y,[RFC8446]
|
||||
50,signature_algorithms_cert,"CH, CR",N,Y,[RFC8446]
|
||||
51,key_share,"CH, SH, HRR",N,Y,[RFC8446]
|
||||
52,transparency_info,"CH, CR, CT",N,Y,[RFC9162]
|
||||
53,connection_id (deprecated),-,Y,N,[RFC9146]
|
||||
54,connection_id,"CH, SH",Y,N,[RFC9146]
|
||||
55,external_id_hash,"CH, EE",N,Y,[RFC8844]
|
||||
56,external_session_id,"CH, EE",N,Y,[RFC8844]
|
||||
57,quic_transport_parameters,"CH, EE",N,Y,[RFC9001]
|
||||
58,ticket_request,"CH, EE",N,Y,[RFC9149]
|
||||
59,dnssec_chain,"CH, CT",N,N,[RFC9102][RFC Errata 6860]
|
||||
60-2569,Unassigned,,,,
|
||||
2570,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
2571-6681,Unassigned,,,,
|
||||
6682,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
6683-10793,Unassigned,,,,
|
||||
10794,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
10795-14905,Unassigned,,,,
|
||||
14906,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
14907-19017,Unassigned,,,,
|
||||
19018,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
19019-23129,Unassigned,,,,
|
||||
23130,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
23131-27241,Unassigned,,,,
|
||||
27242,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
27243-31353,Unassigned,,,,
|
||||
31354,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
31355-35465,Unassigned,,,,
|
||||
35466,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
35467-39577,Unassigned,,,,
|
||||
39578,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
39579-43689,Unassigned,,,,
|
||||
43690,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
43691-47801,Unassigned,,,,
|
||||
47802,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
47803-51913,Unassigned,,,,
|
||||
51914,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
51915-56025,Unassigned,,,,
|
||||
56026,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
56027-60137,Unassigned,,,,
|
||||
60138,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
60139-64249,Unassigned,,,,
|
||||
64250,Reserved,"CH, CR, NST",N,N,[RFC8701]
|
||||
64251-65279,Unassigned,,,,
|
||||
65280,Reserved for Private Use,,,,[RFC8446]
|
||||
65281,renegotiation_info,-,N,Y,[RFC5746]
|
||||
65282-65535,Reserved for Private Use,,,,[RFC8446]
|
|
|
@ -0,0 +1,159 @@
|
|||
// SPDX-FileCopyrightText: 2023 nervuri <https://nervuri.net/contact>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Inspired by Andrew Ayer's tlshacks:
|
||||
// https://github.com/AGWA/tlshacks/blob/main/generate_extensions.go
|
||||
|
||||
package clienthello
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/csv"
|
||||
"io"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values-1.csv
|
||||
//
|
||||
//go:embed extensions.csv
|
||||
var extensionsCSV string
|
||||
|
||||
var ExtensionList = parseExtensionsCSV()
|
||||
|
||||
// === CONSTANTS ===
|
||||
|
||||
// TLS extension codes
|
||||
const (
|
||||
extensionServerName uint16 = 0
|
||||
extensionStatusRequest uint16 = 5
|
||||
extensionSupportedGroups uint16 = 10 // elliptic_curves in TLS versions prior to 1.3, see RFC 8446, Section 4.2.7
|
||||
extensionSupportedPointFormats uint16 = 11
|
||||
extensionSignatureAlgorithms uint16 = 13
|
||||
extensionALPN uint16 = 16
|
||||
extensionSCT uint16 = 18
|
||||
extensionPadding uint16 = 21
|
||||
extensionEncryptThenMac uint16 = 22
|
||||
extensionExtendedMasterSecret uint16 = 23
|
||||
extensionCompressCertificate uint16 = 27
|
||||
extensionSessionTicket uint16 = 35
|
||||
extensionPreSharedKey uint16 = 41
|
||||
extensionEarlyData uint16 = 42
|
||||
extensionSupportedVersions uint16 = 43
|
||||
extensionCookie uint16 = 44
|
||||
extensionPSKModes uint16 = 45
|
||||
extensionCertificateAuthorities uint16 = 47
|
||||
extensionPostHandshakeAuth uint16 = 49
|
||||
extensionSignatureAlgorithmsCert uint16 = 50
|
||||
extensionKeyShare uint16 = 51
|
||||
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
|
||||
extensionApplicationSettings uint16 = 17513 // not IANA assigned
|
||||
extensionRenegotiationInfo uint16 = 0xff01
|
||||
)
|
||||
|
||||
// TLS CertificateStatusType (RFC 3546)
|
||||
const (
|
||||
statusTypeOCSP uint8 = 1
|
||||
)
|
||||
|
||||
// === STRUCTS ===
|
||||
|
||||
// TLS 1.3 PSK Identity. Can be a Session Ticket, or a reference to a saved
|
||||
// session. See RFC 8446, Section 4.2.11.
|
||||
type PSKIdentity struct {
|
||||
Identity byteSlice `json:"identity"`
|
||||
ObfuscatedTicketAge uint32 `json:"obfuscated_ticket_age"`
|
||||
}
|
||||
|
||||
type ExtensionData struct {
|
||||
Raw byteSlice `json:"raw"`
|
||||
ServerName string `json:"server_name,omitempty"`
|
||||
StatusType uint8 `json:"status_type,omitempty"`
|
||||
SupportedGroups []NamedGroup `json:"supported_groups,omitempty"`
|
||||
SupportedPointFormats []ECPointFormat `json:"supported_point_formats,omitempty"`
|
||||
SupportedSignatureAlgorithms []SignatureScheme `json:"supported_signature_algorithms,omitempty"`
|
||||
RenegotiationInfo []byte `json:"renegotiation_info,omitempty"`
|
||||
ALPNProtocols []string `json:"alpn_protocols,omitempty"`
|
||||
SupportedVersions []TLSVersion `json:"supported_tls_versions,omitempty"`
|
||||
Cookie byteSlice `json:"cookie,omitempty"`
|
||||
KeyShares []KeyShare `json:"key_shares,omitempty"`
|
||||
PSKModes []PSKMode `json:"psk_modes,omitempty"`
|
||||
PSKIdentities []PSKIdentity `json:"psk_identities,omitempty"`
|
||||
PSKBinders []byteSlice `json:"psk_binders,omitempty"`
|
||||
Length uint16 `json:"length,omitempty"` // padding
|
||||
}
|
||||
|
||||
type Extension struct {
|
||||
Code uint16 `json:"code"`
|
||||
Name string `json:"name"`
|
||||
Recommended bool `json:"-"`
|
||||
Reference string `json:"-"`
|
||||
Data ExtensionData `json:"data"`
|
||||
}
|
||||
|
||||
// === FUNCTIONS ===
|
||||
|
||||
func parseExtensionsCSV() map[uint16]Extension {
|
||||
extensions := map[uint16]Extension{}
|
||||
r := csv.NewReader(strings.NewReader(extensionsCSV))
|
||||
|
||||
// Skip CSV header.
|
||||
_, err := r.Read()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for {
|
||||
row, err := r.Read()
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
var (
|
||||
val = row[0]
|
||||
name = row[1]
|
||||
rec = row[4]
|
||||
ref = row[5]
|
||||
)
|
||||
if name == "Unassigned" {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(name, "Reserved") && ref != "[RFC8701]" {
|
||||
continue
|
||||
}
|
||||
code, err := strconv.Atoi(val)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
// Deal with names like "supported_groups (renamed from "elliptic_curves")"
|
||||
// by stopping at the first space.
|
||||
name = strings.SplitN(name, " ", 2)[0]
|
||||
ext := Extension{
|
||||
Code: uint16(code),
|
||||
Name: name,
|
||||
Reference: ref,
|
||||
}
|
||||
if rec == "Y" {
|
||||
ext.Recommended = true
|
||||
}
|
||||
if ref == "[RFC8701]" {
|
||||
ext.Name = "GREASE"
|
||||
}
|
||||
|
||||
extensions[ext.Code] = ext
|
||||
}
|
||||
return extensions
|
||||
}
|
||||
|
||||
func GetExtensionInfo(extensionCode uint16) Extension {
|
||||
info, found := ExtensionList[extensionCode]
|
||||
if !found {
|
||||
info = Extension{
|
||||
Code: extensionCode,
|
||||
}
|
||||
}
|
||||
return info
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
Value,Description,DTLS-OK,Recommended,Reference,Comment
|
||||
0,Reserved,,,[RFC8447],
|
||||
1,sect163k1,Y,N,[RFC8422],
|
||||
2,sect163r1,Y,N,[RFC8422],
|
||||
3,sect163r2,Y,N,[RFC8422],
|
||||
4,sect193r1,Y,N,[RFC8422],
|
||||
5,sect193r2,Y,N,[RFC8422],
|
||||
6,sect233k1,Y,N,[RFC8422],
|
||||
7,sect233r1,Y,N,[RFC8422],
|
||||
8,sect239k1,Y,N,[RFC8422],
|
||||
9,sect283k1,Y,N,[RFC8422],
|
||||
10,sect283r1,Y,N,[RFC8422],
|
||||
11,sect409k1,Y,N,[RFC8422],
|
||||
12,sect409r1,Y,N,[RFC8422],
|
||||
13,sect571k1,Y,N,[RFC8422],
|
||||
14,sect571r1,Y,N,[RFC8422],
|
||||
15,secp160k1,Y,N,[RFC8422],
|
||||
16,secp160r1,Y,N,[RFC8422],
|
||||
17,secp160r2,Y,N,[RFC8422],
|
||||
18,secp192k1,Y,N,[RFC8422],
|
||||
19,secp192r1,Y,N,[RFC8422],
|
||||
20,secp224k1,Y,N,[RFC8422],
|
||||
21,secp224r1,Y,N,[RFC8422],
|
||||
22,secp256k1,Y,N,[RFC8422],
|
||||
23,secp256r1,Y,Y,[RFC8422],
|
||||
24,secp384r1,Y,Y,[RFC8422],
|
||||
25,secp521r1,Y,N,[RFC8422],
|
||||
26,brainpoolP256r1,Y,N,[RFC7027],
|
||||
27,brainpoolP384r1,Y,N,[RFC7027],
|
||||
28,brainpoolP512r1,Y,N,[RFC7027],
|
||||
29,x25519,Y,Y,[RFC8446][RFC8422],
|
||||
30,x448,Y,Y,[RFC8446][RFC8422],
|
||||
31,brainpoolP256r1tls13,Y,N,[RFC8734],
|
||||
32,brainpoolP384r1tls13,Y,N,[RFC8734],
|
||||
33,brainpoolP512r1tls13,Y,N,[RFC8734],
|
||||
34,GC256A,Y,N,[RFC9189],
|
||||
35,GC256B,Y,N,[RFC9189],
|
||||
36,GC256C,Y,N,[RFC9189],
|
||||
37,GC256D,Y,N,[RFC9189],
|
||||
38,GC512A,Y,N,[RFC9189],
|
||||
39,GC512B,Y,N,[RFC9189],
|
||||
40,GC512C,Y,N,[RFC9189],
|
||||
41,curveSM2,N,N,[RFC8998],
|
||||
42-255,Unassigned,,,,
|
||||
256,ffdhe2048,Y,N,[RFC7919],
|
||||
257,ffdhe3072,Y,N,[RFC7919],
|
||||
258,ffdhe4096,Y,N,[RFC7919],
|
||||
259,ffdhe6144,Y,N,[RFC7919],
|
||||
260,ffdhe8192,Y,N,[RFC7919],
|
||||
261-507,Unassigned,,,,
|
||||
508-511,Reserved for Private Use,,,[RFC7919],
|
||||
512-2569,Unassigned,,,,
|
||||
2570,Reserved,Y,N,[RFC8701],
|
||||
2571-6681,Unassigned,,,,
|
||||
6682,Reserved,Y,N,[RFC8701],
|
||||
6683-10793,Unassigned,,,,
|
||||
10794,Reserved,Y,N,[RFC8701],
|
||||
10795-14905,Unassigned,,,,
|
||||
14906,Reserved,Y,N,[RFC8701],
|
||||
14907-19017,Unassigned,,,,
|
||||
19018,Reserved,Y,N,[RFC8701],
|
||||
19019-23129,Unassigned,,,,
|
||||
23130,Reserved,Y,N,[RFC8701],
|
||||
23131-27241,Unassigned,,,,
|
||||
27242,Reserved,Y,N,[RFC8701],
|
||||
27243-31353,Unassigned,,,,
|
||||
31354,Reserved,Y,N,[RFC8701],
|
||||
31355-35465,Unassigned,,,,
|
||||
35466,Reserved,Y,N,[RFC8701],
|
||||
35467-39577,Unassigned,,,,
|
||||
39578,Reserved,Y,N,[RFC8701],
|
||||
39579-43689,Unassigned,,,,
|
||||
43690,Reserved,Y,N,[RFC8701],
|
||||
43691-47801,Unassigned,,,,
|
||||
47802,Reserved,Y,N,[RFC8701],
|
||||
47803-51913,Unassigned,,,,
|
||||
51914,Reserved,Y,N,[RFC8701],
|
||||
51915-56025,Unassigned,,,,
|
||||
56026,Reserved,Y,N,[RFC8701],
|
||||
56027-60137,Unassigned,,,,
|
||||
60138,Reserved,Y,N,[RFC8701],
|
||||
60139-64249,Unassigned,,,,
|
||||
64250,Reserved,Y,N,[RFC8701],
|
||||
64251-65023,Unassigned,,,,
|
||||
65024-65279,Reserved for Private Use,,,[RFC8422],
|
||||
65280,Unassigned,,,,
|
||||
65281,arbitrary_explicit_prime_curves,Y,N,[RFC8422],
|
||||
65282,arbitrary_explicit_char2_curves,Y,N,[RFC8422],
|
||||
65283-65535,Unassigned,,,,
|
|
|
@ -0,0 +1,118 @@
|
|||
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package clienthello
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// RFC 8446, Section 4.2.7
|
||||
// https://www.rfc-editor.org/rfc/rfc8446.html#section-4.2.7
|
||||
// https://www.iana.org/assignments/tls-parameters/tls-parameters-8.csv
|
||||
//
|
||||
//go:embed named-groups.csv
|
||||
var namedGroupsCSV string
|
||||
|
||||
var NamedGroupList = parseNamedGroupsCSV()
|
||||
|
||||
type NamedGroup any // (uint16 | NamedGroupInfo)
|
||||
|
||||
type NamedGroupInfo struct {
|
||||
Code uint16 `json:"code"`
|
||||
HexCode string `json:"hex_code"`
|
||||
Name string `json:"name"`
|
||||
Recommended bool `json:"-"`
|
||||
Reference string `json:"-"`
|
||||
}
|
||||
|
||||
// TLS 1.3 Key Share. See RFC 8446, Section 4.2.8.
|
||||
type KeyShare struct {
|
||||
Group NamedGroup `json:"group"`
|
||||
Data byteSlice `json:"data"`
|
||||
}
|
||||
|
||||
func parseNamedGroupsCSV() map[uint16]NamedGroupInfo {
|
||||
namedGroups := map[uint16]NamedGroupInfo{}
|
||||
r := csv.NewReader(strings.NewReader(namedGroupsCSV))
|
||||
|
||||
// Skip CSV header.
|
||||
_, err := r.Read()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for {
|
||||
row, err := r.Read()
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
var (
|
||||
val = row[0]
|
||||
desc = row[1]
|
||||
rec = row[3]
|
||||
ref = row[4]
|
||||
)
|
||||
if desc == "Unassigned" {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(desc, "Reserved") && ref != "[RFC8701]" {
|
||||
continue
|
||||
}
|
||||
code, err := strconv.Atoi(val)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
group := NamedGroupInfo{
|
||||
Code: uint16(code),
|
||||
HexCode: fmt.Sprintf("%04X", code),
|
||||
Name: desc,
|
||||
Reference: ref,
|
||||
}
|
||||
if rec == "Y" {
|
||||
group.Recommended = true
|
||||
}
|
||||
if ref == "[RFC8701]" {
|
||||
group.Name = "GREASE"
|
||||
}
|
||||
|
||||
namedGroups[group.Code] = group
|
||||
}
|
||||
return namedGroups
|
||||
}
|
||||
|
||||
func GetNamedGroupInfo(namedGroupCode uint16) NamedGroupInfo {
|
||||
info, found := NamedGroupList[namedGroupCode]
|
||||
if !found {
|
||||
info = NamedGroupInfo{
|
||||
Code: namedGroupCode,
|
||||
HexCode: fmt.Sprintf("%04X", namedGroupCode),
|
||||
}
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func (m *ClientHelloMsg) AddNamedGroupInfo() {
|
||||
for i, ext := range m.Extensions {
|
||||
switch ext.Code {
|
||||
case extensionSupportedGroups:
|
||||
for j, group := range ext.Data.SupportedGroups {
|
||||
m.Extensions[i].Data.SupportedGroups[j] = GetNamedGroupInfo(group.(uint16))
|
||||
}
|
||||
case extensionKeyShare:
|
||||
for j, kShare := range ext.Data.KeyShares {
|
||||
m.Extensions[i].Data.KeyShares[j].Group = GetNamedGroupInfo(
|
||||
kShare.Group.(uint16))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package clienthello
|
||||
|
||||
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9
|
||||
var ECPointFormatList = map[uint8]ECPointFormatInfo{
|
||||
0: {Code: 0, Name: "uncompressed", Reference: "[RFC8422]"},
|
||||
1: {Code: 1, Name: "ansiX962_compressed_prime", Reference: "[RFC8422]"},
|
||||
2: {Code: 2, Name: "ansiX962_compressed_char2", Reference: "[RFC8422]"},
|
||||
}
|
||||
|
||||
type ECPointFormat any // (uint8 | ECPointFormatInfo)
|
||||
|
||||
type ECPointFormatInfo struct {
|
||||
Code uint8 `json:"code"`
|
||||
Name string `json:"name"`
|
||||
Reference string `json:"-"`
|
||||
}
|
||||
|
||||
func GetECPointFormatInfo(ecPointFormatCode uint8) ECPointFormatInfo {
|
||||
info, found := ECPointFormatList[ecPointFormatCode]
|
||||
if !found {
|
||||
info = ECPointFormatInfo{
|
||||
Code: ecPointFormatCode,
|
||||
}
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func (m *ClientHelloMsg) AddECPointFormatInfo() {
|
||||
for i, ext := range m.Extensions {
|
||||
if ext.Code == extensionSupportedPointFormats {
|
||||
for j, pointFormat := range ext.Data.SupportedPointFormats {
|
||||
m.Extensions[i].Data.SupportedPointFormats[j] = GetECPointFormatInfo(
|
||||
pointFormat.(uint8))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// PSK Key Exchange Modes
|
||||
|
||||
package clienthello
|
||||
|
||||
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-pskkeyexchangemode
|
||||
// https://www.rfc-editor.org/rfc/rfc8446.html#section-4.2.9
|
||||
var PSKModeList = map[uint8]PSKModeInfo{
|
||||
0: {Code: 0, Name: "psk_ke", Recommended: true, Reference: "[RFC8446]"},
|
||||
1: {Code: 1, Name: "psk_dhe_ke", Recommended: true, Reference: "[RFC8446]"},
|
||||
|
||||
0x0B: {Code: 0x0B, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
|
||||
0x2A: {Code: 0x2A, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
|
||||
0x49: {Code: 0x49, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
|
||||
0x68: {Code: 0x68, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
|
||||
0x87: {Code: 0x87, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
|
||||
0xA6: {Code: 0xA6, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
|
||||
0xC5: {Code: 0xC5, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
|
||||
0xE4: {Code: 0xE4, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
|
||||
}
|
||||
|
||||
type PSKMode any // (uint8 | PSKModeInfo)
|
||||
|
||||
type PSKModeInfo struct {
|
||||
Code uint8 `json:"code"`
|
||||
Name string `json:"name"`
|
||||
Recommended bool `json:"-"`
|
||||
Reference string `json:"-"`
|
||||
}
|
||||
|
||||
func GetPSKModeInfo(pskModeCode uint8) PSKModeInfo {
|
||||
info, found := PSKModeList[pskModeCode]
|
||||
if !found {
|
||||
info = PSKModeInfo{
|
||||
Code: pskModeCode,
|
||||
}
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func (m *ClientHelloMsg) AddPSKModeInfo() {
|
||||
for i, ext := range m.Extensions {
|
||||
if ext.Code == extensionPSKModes {
|
||||
for j, pskMode := range ext.Data.PSKModes {
|
||||
m.Extensions[i].Data.PSKModes[j] = GetPSKModeInfo(pskMode.(uint8))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,545 @@
|
|||
Value,Description,Recommended,Reference
|
||||
0x0000-0x0200,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0201,rsa_pkcs1_sha1,N,[RFC8446][RFC9155]
|
||||
0x0202,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0203,ecdsa_sha1,N,[RFC8446][RFC9155]
|
||||
0x0204-0x0400,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0401,rsa_pkcs1_sha256,Y,[RFC8446]
|
||||
0x0402,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0403,ecdsa_secp256r1_sha256,Y,[RFC8446]
|
||||
0x0404-0x041F,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0420,rsa_pkcs1_sha256_legacy,N,[draft-davidben-tls13-pkcs1-00]
|
||||
0x0421-0x0500,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0501,rsa_pkcs1_sha384,Y,[RFC8446]
|
||||
0x0502,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0503,ecdsa_secp384r1_sha384,Y,[RFC8446]
|
||||
0x0504-0x051F,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0520,rsa_pkcs1_sha384_legacy,N,[draft-davidben-tls13-pkcs1-00]
|
||||
0x0521-0x0600,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0601,rsa_pkcs1_sha512,Y,[RFC8446]
|
||||
0x0602,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0603,ecdsa_secp521r1_sha512,Y,[RFC8446]
|
||||
0x0604-0x061F,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0620,rsa_pkcs1_sha512_legacy,N,[draft-davidben-tls13-pkcs1-00]
|
||||
0x0621-0x0703,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0704,eccsi_sha256,N,[draft-wang-tls-raw-public-key-with-ibc]
|
||||
0x0705,iso_ibs1,N,[draft-wang-tls-raw-public-key-with-ibc]
|
||||
0x0706,iso_ibs2,N,[draft-wang-tls-raw-public-key-with-ibc]
|
||||
0x0707,iso_chinese_ibs,N,[draft-wang-tls-raw-public-key-with-ibc]
|
||||
0x0708,sm2sig_sm3,N,[RFC8998]
|
||||
0x0709,gostr34102012_256a,N,[RFC9367]
|
||||
0x070A,gostr34102012_256b,N,[RFC9367]
|
||||
0x070B,gostr34102012_256c,N,[RFC9367]
|
||||
0x070C,gostr34102012_256d,N,[RFC9367]
|
||||
0x070D,gostr34102012_512a,N,[RFC9367]
|
||||
0x070E,gostr34102012_512b,N,[RFC9367]
|
||||
0x070F,gostr34102012_512c,N,[RFC9367]
|
||||
0x0710-0x07FF,Unassigned,,
|
||||
0x0800-0x0803,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0804,rsa_pss_rsae_sha256,Y,[RFC8446]
|
||||
0x0805,rsa_pss_rsae_sha384,Y,[RFC8446]
|
||||
0x0806,rsa_pss_rsae_sha512,Y,[RFC8446]
|
||||
0x0807,ed25519,Y,[RFC8446]
|
||||
0x0808,ed448,Y,[RFC8446]
|
||||
0x0809,rsa_pss_pss_sha256,Y,[RFC8446]
|
||||
0x080A,rsa_pss_pss_sha384,Y,[RFC8446]
|
||||
0x080B,rsa_pss_pss_sha512,Y,[RFC8446]
|
||||
0x080C-0x0819,Unassigned,,
|
||||
0x081A,ecdsa_brainpoolP256r1tls13_sha256,N,[RFC8734]
|
||||
0x081B,ecdsa_brainpoolP384r1tls13_sha384,N,[RFC8734]
|
||||
0x081C,ecdsa_brainpoolP512r1tls13_sha512,N,[RFC8734]
|
||||
0x081D-0x083F,Unassigned,,
|
||||
0x0840,Reserved for backward compatibility,N,[RFC9189]
|
||||
0x0841,Reserved for backward compatibility,N,[RFC9189]
|
||||
0x0842-0x08FF,Unassigned,,
|
||||
0x0900-0x0903,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0904-0x09FF,Unassigned,,
|
||||
0x0A00-0x0A03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0A04-0x0AFF,Unassigned,,
|
||||
0x0B00-0x0B03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0B04-0x0BFF,Unassigned,,
|
||||
0x0C00-0x0C03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0C04-0x0CFF,Unassigned,,
|
||||
0x0D00-0x0D03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0D04-0x0DFF,Unassigned,,
|
||||
0x0E00-0x0E03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0E04-0x0EFF,Unassigned,,
|
||||
0x0F00-0x0F03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x0F04-0x0FFF,Unassigned,,
|
||||
0x1000-0x1003,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1004-0x10FF,Unassigned,,
|
||||
0x1100-0x1103,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1104-0x11FF,Unassigned,,
|
||||
0x1200-0x1203,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1204-0x12FF,Unassigned,,
|
||||
0x1300-0x1303,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1304-0x13FF,Unassigned,,
|
||||
0x1400-0x1403,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1404-0x14FF,Unassigned,,
|
||||
0x1500-0x1503,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1504-0x15FF,Unassigned,,
|
||||
0x1600-0x1603,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1604-0x16FF,Unassigned,,
|
||||
0x1700-0x1703,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1704-0x17FF,Unassigned,,
|
||||
0x1800-0x1803,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1804-0x18FF,Unassigned,,
|
||||
0x1900-0x1903,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1904-0x19FF,Unassigned,,
|
||||
0x1A00-0x1A03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1A04-0x1AFF,Unassigned,,
|
||||
0x1B00-0x1B03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1B04-0x1BFF,Unassigned,,
|
||||
0x1C00-0x1C03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1C04-0x1CFF,Unassigned,,
|
||||
0x1D00-0x1D03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1D04-0x1DFF,Unassigned,,
|
||||
0x1E00-0x1E03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1E04-0x1EFF,Unassigned,,
|
||||
0x1F00-0x1F03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x1F04-0x1FFF,Unassigned,,
|
||||
0x2000-0x2003,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2004-0x20FF,Unassigned,,
|
||||
0x2100-0x2103,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2104-0x21FF,Unassigned,,
|
||||
0x2200-0x2203,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2204-0x22FF,Unassigned,,
|
||||
0x2300-0x2303,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2304-0x23FF,Unassigned,,
|
||||
0x2400-0x2403,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2404-0x24FF,Unassigned,,
|
||||
0x2500-0x2503,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2504-0x25FF,Unassigned,,
|
||||
0x2600-0x2603,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2604-0x26FF,Unassigned,,
|
||||
0x2700-0x2703,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2704-0x27FF,Unassigned,,
|
||||
0x2800-0x2803,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2804-0x28FF,Unassigned,,
|
||||
0x2900-0x2903,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2904-0x29FF,Unassigned,,
|
||||
0x2A00-0x2A03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2A04-0x2AFF,Unassigned,,
|
||||
0x2B00-0x2B03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2B04-0x2BFF,Unassigned,,
|
||||
0x2C00-0x2C03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2C04-0x2CFF,Unassigned,,
|
||||
0x2D00-0x2D03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2D04-0x2DFF,Unassigned,,
|
||||
0x2E00-0x2E03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2E04-0x2EFF,Unassigned,,
|
||||
0x2F00-0x2F03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x2F04-0x2FFF,Unassigned,,
|
||||
0x3000-0x3003,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3004-0x30FF,Unassigned,,
|
||||
0x3100-0x3103,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3104-0x31FF,Unassigned,,
|
||||
0x3200-0x3203,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3204-0x32FF,Unassigned,,
|
||||
0x3300-0x3303,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3304-0x33FF,Unassigned,,
|
||||
0x3400-0x3403,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3404-0x34FF,Unassigned,,
|
||||
0x3500-0x3503,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3504-0x35FF,Unassigned,,
|
||||
0x3600-0x3603,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3604-0x36FF,Unassigned,,
|
||||
0x3700-0x3703,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3704-0x37FF,Unassigned,,
|
||||
0x3800-0x3803,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3804-0x38FF,Unassigned,,
|
||||
0x3900-0x3903,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3904-0x39FF,Unassigned,,
|
||||
0x3A00-0x3A03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3A04-0x3AFF,Unassigned,,
|
||||
0x3B00-0x3B03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3B04-0x3BFF,Unassigned,,
|
||||
0x3C00-0x3C03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3C04-0x3CFF,Unassigned,,
|
||||
0x3D00-0x3D03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3D04-0x3DFF,Unassigned,,
|
||||
0x3E00-0x3E03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3E04-0x3EFF,Unassigned,,
|
||||
0x3F00-0x3F03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x3F04-0x3FFF,Unassigned,,
|
||||
0x4000-0x4003,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4004-0x40FF,Unassigned,,
|
||||
0x4100-0x4103,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4104-0x41FF,Unassigned,,
|
||||
0x4200-0x4203,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4204-0x42FF,Unassigned,,
|
||||
0x4300-0x4303,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4304-0x43FF,Unassigned,,
|
||||
0x4400-0x4403,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4404-0x44FF,Unassigned,,
|
||||
0x4500-0x4503,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4504-0x45FF,Unassigned,,
|
||||
0x4600-0x4603,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4604-0x46FF,Unassigned,,
|
||||
0x4700-0x4703,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4704-0x47FF,Unassigned,,
|
||||
0x4800-0x4803,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4804-0x48FF,Unassigned,,
|
||||
0x4900-0x4903,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4904-0x49FF,Unassigned,,
|
||||
0x4A00-0x4A03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4A04-0x4AFF,Unassigned,,
|
||||
0x4B00-0x4B03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4B04-0x4BFF,Unassigned,,
|
||||
0x4C00-0x4C03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4C04-0x4CFF,Unassigned,,
|
||||
0x4D00-0x4D03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4D04-0x4DFF,Unassigned,,
|
||||
0x4E00-0x4E03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4E04-0x4EFF,Unassigned,,
|
||||
0x4F00-0x4F03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x4F04-0x4FFF,Unassigned,,
|
||||
0x5000-0x5003,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5004-0x50FF,Unassigned,,
|
||||
0x5100-0x5103,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5104-0x51FF,Unassigned,,
|
||||
0x5200-0x5203,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5204-0x52FF,Unassigned,,
|
||||
0x5300-0x5303,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5304-0x53FF,Unassigned,,
|
||||
0x5400-0x5403,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5404-0x54FF,Unassigned,,
|
||||
0x5500-0x5503,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5504-0x55FF,Unassigned,,
|
||||
0x5600-0x5603,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5604-0x56FF,Unassigned,,
|
||||
0x5700-0x5703,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5704-0x57FF,Unassigned,,
|
||||
0x5800-0x5803,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5804-0x58FF,Unassigned,,
|
||||
0x5900-0x5903,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5904-0x59FF,Unassigned,,
|
||||
0x5A00-0x5A03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5A04-0x5AFF,Unassigned,,
|
||||
0x5B00-0x5B03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5B04-0x5BFF,Unassigned,,
|
||||
0x5C00-0x5C03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5C04-0x5CFF,Unassigned,,
|
||||
0x5D00-0x5D03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5D04-0x5DFF,Unassigned,,
|
||||
0x5E00-0x5E03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5E04-0x5EFF,Unassigned,,
|
||||
0x5F00-0x5F03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x5F04-0x5FFF,Unassigned,,
|
||||
0x6000-0x6003,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6004-0x60FF,Unassigned,,
|
||||
0x6100-0x6103,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6104-0x61FF,Unassigned,,
|
||||
0x6200-0x6203,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6204-0x62FF,Unassigned,,
|
||||
0x6300-0x6303,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6304-0x63FF,Unassigned,,
|
||||
0x6400-0x6403,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6404-0x64FF,Unassigned,,
|
||||
0x6500-0x6503,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6504-0x65FF,Unassigned,,
|
||||
0x6600-0x6603,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6604-0x66FF,Unassigned,,
|
||||
0x6700-0x6703,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6704-0x67FF,Unassigned,,
|
||||
0x6800-0x6803,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6804-0x68FF,Unassigned,,
|
||||
0x6900-0x6903,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6904-0x69FF,Unassigned,,
|
||||
0x6A00-0x6A03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6A04-0x6AFF,Unassigned,,
|
||||
0x6B00-0x6B03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6B04-0x6BFF,Unassigned,,
|
||||
0x6C00-0x6C03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6C04-0x6CFF,Unassigned,,
|
||||
0x6D00-0x6D03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6D04-0x6DFF,Unassigned,,
|
||||
0x6E00-0x6E03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6E04-0x6EFF,Unassigned,,
|
||||
0x6F00-0x6F03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x6F04-0x6FFF,Unassigned,,
|
||||
0x7000-0x7003,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7004-0x70FF,Unassigned,,
|
||||
0x7100-0x7103,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7104-0x71FF,Unassigned,,
|
||||
0x7200-0x7203,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7204-0x72FF,Unassigned,,
|
||||
0x7300-0x7303,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7304-0x73FF,Unassigned,,
|
||||
0x7400-0x7403,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7404-0x74FF,Unassigned,,
|
||||
0x7500-0x7503,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7504-0x75FF,Unassigned,,
|
||||
0x7600-0x7603,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7604-0x76FF,Unassigned,,
|
||||
0x7700-0x7703,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7704-0x77FF,Unassigned,,
|
||||
0x7800-0x7803,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7804-0x78FF,Unassigned,,
|
||||
0x7900-0x7903,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7904-0x79FF,Unassigned,,
|
||||
0x7A00-0x7A03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7A04-0x7AFF,Unassigned,,
|
||||
0x7B00-0x7B03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7B04-0x7BFF,Unassigned,,
|
||||
0x7C00-0x7C03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7C04-0x7CFF,Unassigned,,
|
||||
0x7D00-0x7D03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7D04-0x7DFF,Unassigned,,
|
||||
0x7E00-0x7E03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7E04-0x7EFF,Unassigned,,
|
||||
0x7F00-0x7F03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x7F04-0x7FFF,Unassigned,,
|
||||
0x8000-0x8003,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8004-0x80FF,Unassigned,,
|
||||
0x8100-0x8103,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8104-0x81FF,Unassigned,,
|
||||
0x8200-0x8203,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8204-0x82FF,Unassigned,,
|
||||
0x8300-0x8303,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8304-0x83FF,Unassigned,,
|
||||
0x8400-0x8403,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8404-0x84FF,Unassigned,,
|
||||
0x8500-0x8503,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8504-0x85FF,Unassigned,,
|
||||
0x8600-0x8603,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8604-0x86FF,Unassigned,,
|
||||
0x8700-0x8703,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8704-0x87FF,Unassigned,,
|
||||
0x8800-0x8803,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8804-0x88FF,Unassigned,,
|
||||
0x8900-0x8903,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8904-0x89FF,Unassigned,,
|
||||
0x8A00-0x8A03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8A04-0x8AFF,Unassigned,,
|
||||
0x8B00-0x8B03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8B04-0x8BFF,Unassigned,,
|
||||
0x8C00-0x8C03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8C04-0x8CFF,Unassigned,,
|
||||
0x8D00-0x8D03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8D04-0x8DFF,Unassigned,,
|
||||
0x8E00-0x8E03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8E04-0x8EFF,Unassigned,,
|
||||
0x8F00-0x8F03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x8F04-0x8FFF,Unassigned,,
|
||||
0x9000-0x9003,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9004-0x90FF,Unassigned,,
|
||||
0x9100-0x9103,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9104-0x91FF,Unassigned,,
|
||||
0x9200-0x9203,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9204-0x92FF,Unassigned,,
|
||||
0x9300-0x9303,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9304-0x93FF,Unassigned,,
|
||||
0x9400-0x9403,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9404-0x94FF,Unassigned,,
|
||||
0x9500-0x9503,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9504-0x95FF,Unassigned,,
|
||||
0x9600-0x9603,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9604-0x96FF,Unassigned,,
|
||||
0x9700-0x9703,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9704-0x97FF,Unassigned,,
|
||||
0x9800-0x9803,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9804-0x98FF,Unassigned,,
|
||||
0x9900-0x9903,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9904-0x99FF,Unassigned,,
|
||||
0x9A00-0x9A03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9A04-0x9AFF,Unassigned,,
|
||||
0x9B00-0x9B03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9B04-0x9BFF,Unassigned,,
|
||||
0x9C00-0x9C03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9C04-0x9CFF,Unassigned,,
|
||||
0x9D00-0x9D03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9D04-0x9DFF,Unassigned,,
|
||||
0x9E00-0x9E03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9E04-0x9EFF,Unassigned,,
|
||||
0x9F00-0x9F03,Reserved for backward compatibility,,[RFC8446]
|
||||
0x9F04-0x9FFF,Unassigned,,
|
||||
0xA000-0xA003,Reserved for backward compatibility,,[RFC8446]
|
||||
0xA004-0xA0FF,Unassigned,,
|
||||
0xA100-0xA103,Reserved for backward compatibility,,[RFC8446]
|
||||
0xA104-0xA1FF,Unassigned,,
|
||||
0xA200-0xA203,Reserved for backward compatibility,,[RFC8446]
|
||||
0xA204-0xA2FF,Unassigned,,
|
||||
0xA300-0xA303,Reserved for backward compatibility,,[RFC8446]
|
||||
0xA304-0xA3FF,Unassigned,,
|
||||
0xA400-0xA403,Reserved for backward compatibility,,[RFC8446]
|
||||
0xA404-0xA4FF,Unassigned,,
|
||||
0xA500-0xA503,Reserved for backward compatibility,,[RFC8446]
|
||||
0xA504-0xA5FF,Unassigned,,
|
||||
0xA600-0xA603,Reserved for backward compatibility,,[RFC8446]
|
||||
0xA604-0xA6FF,Unassigned,,
|
||||
0xA700-0xA703,Reserved for backward compatibility,,[RFC8446]
|
||||
0xA704-0xA7FF,Unassigned,,
|
||||
0xA800-0xA803,Reserved for backward compatibility,,[RFC8446]
|
||||
0xA804-0xA8FF,Unassigned,,
|
||||
0xA900-0xA903,Reserved for backward compatibility,,[RFC8446]
|
||||
0xA904-0xA9FF,Unassigned,,
|
||||
0xAA00-0xAA03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xAA04-0xAAFF,Unassigned,,
|
||||
0xAB00-0xAB03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xAB04-0xABFF,Unassigned,,
|
||||
0xAC00-0xAC03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xAC04-0xACFF,Unassigned,,
|
||||
0xAD00-0xAD03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xAD04-0xADFF,Unassigned,,
|
||||
0xAE00-0xAE03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xAE04-0xAEFF,Unassigned,,
|
||||
0xAF00-0xAF03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xAF04-0xAFFF,Unassigned,,
|
||||
0xB000-0xB003,Reserved for backward compatibility,,[RFC8446]
|
||||
0xB004-0xB0FF,Unassigned,,
|
||||
0xB100-0xB103,Reserved for backward compatibility,,[RFC8446]
|
||||
0xB104-0xB1FF,Unassigned,,
|
||||
0xB200-0xB203,Reserved for backward compatibility,,[RFC8446]
|
||||
0xB204-0xB2FF,Unassigned,,
|
||||
0xB300-0xB303,Reserved for backward compatibility,,[RFC8446]
|
||||
0xB304-0xB3FF,Unassigned,,
|
||||
0xB400-0xB403,Reserved for backward compatibility,,[RFC8446]
|
||||
0xB404-0xB4FF,Unassigned,,
|
||||
0xB500-0xB503,Reserved for backward compatibility,,[RFC8446]
|
||||
0xB504-0xB5FF,Unassigned,,
|
||||
0xB600-0xB603,Reserved for backward compatibility,,[RFC8446]
|
||||
0xB604-0xB6FF,Unassigned,,
|
||||
0xB700-0xB703,Reserved for backward compatibility,,[RFC8446]
|
||||
0xB704-0xB7FF,Unassigned,,
|
||||
0xB800-0xB803,Reserved for backward compatibility,,[RFC8446]
|
||||
0xB804-0xB8FF,Unassigned,,
|
||||
0xB900-0xB903,Reserved for backward compatibility,,[RFC8446]
|
||||
0xB904-0xB9FF,Unassigned,,
|
||||
0xBA00-0xBA03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xBA04-0xBAFF,Unassigned,,
|
||||
0xBB00-0xBB03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xBB04-0xBBFF,Unassigned,,
|
||||
0xBC00-0xBC03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xBC04-0xBCFF,Unassigned,,
|
||||
0xBD00-0xBD03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xBD04-0xBDFF,Unassigned,,
|
||||
0xBE00-0xBE03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xBE04-0xBEFF,Unassigned,,
|
||||
0xBF00-0xBF03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xBF04-0xBFFF,Unassigned,,
|
||||
0xC000-0xC003,Reserved for backward compatibility,,[RFC8446]
|
||||
0xC004-0xC0FF,Unassigned,,
|
||||
0xC100-0xC103,Reserved for backward compatibility,,[RFC8446]
|
||||
0xC104-0xC1FF,Unassigned,,
|
||||
0xC200-0xC203,Reserved for backward compatibility,,[RFC8446]
|
||||
0xC204-0xC2FF,Unassigned,,
|
||||
0xC300-0xC303,Reserved for backward compatibility,,[RFC8446]
|
||||
0xC304-0xC3FF,Unassigned,,
|
||||
0xC400-0xC403,Reserved for backward compatibility,,[RFC8446]
|
||||
0xC404-0xC4FF,Unassigned,,
|
||||
0xC500-0xC503,Reserved for backward compatibility,,[RFC8446]
|
||||
0xC504-0xC5FF,Unassigned,,
|
||||
0xC600-0xC603,Reserved for backward compatibility,,[RFC8446]
|
||||
0xC604-0xC6FF,Unassigned,,
|
||||
0xC700-0xC703,Reserved for backward compatibility,,[RFC8446]
|
||||
0xC704-0xC7FF,Unassigned,,
|
||||
0xC800-0xC803,Reserved for backward compatibility,,[RFC8446]
|
||||
0xC804-0xC8FF,Unassigned,,
|
||||
0xC900-0xC903,Reserved for backward compatibility,,[RFC8446]
|
||||
0xC904-0xC9FF,Unassigned,,
|
||||
0xCA00-0xCA03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xCA04-0xCAFF,Unassigned,,
|
||||
0xCB00-0xCB03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xCB04-0xCBFF,Unassigned,,
|
||||
0xCC00-0xCC03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xCC04-0xCCFF,Unassigned,,
|
||||
0xCD00-0xCD03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xCD04-0xCDFF,Unassigned,,
|
||||
0xCE00-0xCE03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xCE04-0xCEFF,Unassigned,,
|
||||
0xCF00-0xCF03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xCF04-0xCFFF,Unassigned,,
|
||||
0xD000-0xD003,Reserved for backward compatibility,,[RFC8446]
|
||||
0xD004-0xD0FF,Unassigned,,
|
||||
0xD100-0xD103,Reserved for backward compatibility,,[RFC8446]
|
||||
0xD104-0xD1FF,Unassigned,,
|
||||
0xD200-0xD203,Reserved for backward compatibility,,[RFC8446]
|
||||
0xD204-0xD2FF,Unassigned,,
|
||||
0xD300-0xD303,Reserved for backward compatibility,,[RFC8446]
|
||||
0xD304-0xD3FF,Unassigned,,
|
||||
0xD400-0xD403,Reserved for backward compatibility,,[RFC8446]
|
||||
0xD404-0xD4FF,Unassigned,,
|
||||
0xD500-0xD503,Reserved for backward compatibility,,[RFC8446]
|
||||
0xD504-0xD5FF,Unassigned,,
|
||||
0xD600-0xD603,Reserved for backward compatibility,,[RFC8446]
|
||||
0xD604-0xD6FF,Unassigned,,
|
||||
0xD700-0xD703,Reserved for backward compatibility,,[RFC8446]
|
||||
0xD704-0xD7FF,Unassigned,,
|
||||
0xD800-0xD803,Reserved for backward compatibility,,[RFC8446]
|
||||
0xD804-0xD8FF,Unassigned,,
|
||||
0xD900-0xD903,Reserved for backward compatibility,,[RFC8446]
|
||||
0xD904-0xD9FF,Unassigned,,
|
||||
0xDA00-0xDA03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xDA04-0xDAFF,Unassigned,,
|
||||
0xDB00-0xDB03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xDB04-0xDBFF,Unassigned,,
|
||||
0xDC00-0xDC03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xDC04-0xDCFF,Unassigned,,
|
||||
0xDD00-0xDD03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xDD04-0xDDFF,Unassigned,,
|
||||
0xDE00-0xDE03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xDE04-0xDEFF,Unassigned,,
|
||||
0xDF00-0xDF03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xDF04-0xDFFF,Unassigned,,
|
||||
0xE000-0xE003,Reserved for backward compatibility,,[RFC8446]
|
||||
0xE004-0xE0FF,Unassigned,,
|
||||
0xE100-0xE103,Reserved for backward compatibility,,[RFC8446]
|
||||
0xE104-0xE1FF,Unassigned,,
|
||||
0xE200-0xE203,Reserved for backward compatibility,,[RFC8446]
|
||||
0xE204-0xE2FF,Unassigned,,
|
||||
0xE300-0xE303,Reserved for backward compatibility,,[RFC8446]
|
||||
0xE304-0xE3FF,Unassigned,,
|
||||
0xE400-0xE403,Reserved for backward compatibility,,[RFC8446]
|
||||
0xE404-0xE4FF,Unassigned,,
|
||||
0xE500-0xE503,Reserved for backward compatibility,,[RFC8446]
|
||||
0xE504-0xE5FF,Unassigned,,
|
||||
0xE600-0xE603,Reserved for backward compatibility,,[RFC8446]
|
||||
0xE604-0xE6FF,Unassigned,,
|
||||
0xE700-0xE703,Reserved for backward compatibility,,[RFC8446]
|
||||
0xE704-0xE7FF,Unassigned,,
|
||||
0xE800-0xE803,Reserved for backward compatibility,,[RFC8446]
|
||||
0xE804-0xE8FF,Unassigned,,
|
||||
0xE900-0xE903,Reserved for backward compatibility,,[RFC8446]
|
||||
0xE904-0xE9FF,Unassigned,,
|
||||
0xEA00-0xEA03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xEA04-0xEAFF,Unassigned,,
|
||||
0xEB00-0xEB03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xEB04-0xEBFF,Unassigned,,
|
||||
0xEC00-0xEC03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xEC04-0xECFF,Unassigned,,
|
||||
0xED00-0xED03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xED04-0xEDFF,Unassigned,,
|
||||
0xEE00-0xEE03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xEE04-0xEEFF,Unassigned,,
|
||||
0xEF00-0xEF03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xEF04-0xEFFF,Unassigned,,
|
||||
0xF000-0xF003,Reserved for backward compatibility,,[RFC8446]
|
||||
0xF004-0xF0FF,Unassigned,,
|
||||
0xF100-0xF103,Reserved for backward compatibility,,[RFC8446]
|
||||
0xF104-0xF1FF,Unassigned,,
|
||||
0xF200-0xF203,Reserved for backward compatibility,,[RFC8446]
|
||||
0xF204-0xF2FF,Unassigned,,
|
||||
0xF300-0xF303,Reserved for backward compatibility,,[RFC8446]
|
||||
0xF304-0xF3FF,Unassigned,,
|
||||
0xF400-0xF403,Reserved for backward compatibility,,[RFC8446]
|
||||
0xF404-0xF4FF,Unassigned,,
|
||||
0xF500-0xF503,Reserved for backward compatibility,,[RFC8446]
|
||||
0xF504-0xF5FF,Unassigned,,
|
||||
0xF600-0xF603,Reserved for backward compatibility,,[RFC8446]
|
||||
0xF604-0xF6FF,Unassigned,,
|
||||
0xF700-0xF703,Reserved for backward compatibility,,[RFC8446]
|
||||
0xF704-0xF7FF,Unassigned,,
|
||||
0xF800-0xF803,Reserved for backward compatibility,,[RFC8446]
|
||||
0xF804-0xF8FF,Unassigned,,
|
||||
0xF900-0xF903,Reserved for backward compatibility,,[RFC8446]
|
||||
0xF904-0xF9FF,Unassigned,,
|
||||
0xFA00-0xFA03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xFA04-0xFAFF,Unassigned,,
|
||||
0xFB00-0xFB03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xFB04-0xFBFF,Unassigned,,
|
||||
0xFC00-0xFC03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xFC04-0xFCFF,Unassigned,,
|
||||
0xFD00-0xFD03,Reserved for backward compatibility,,[RFC8446]
|
||||
0xFD04-0xFDFF,Unassigned,,
|
||||
0xFE00-0xFFFF,Reserved for Private Use,,[RFC8446]
|
|
|
@ -0,0 +1,111 @@
|
|||
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package clienthello
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// RFC 8446, Section 4.2.3
|
||||
// https://www.rfc-editor.org/rfc/rfc8446.html#section-4.2.3
|
||||
// https://www.iana.org/assignments/tls-parameters/tls-signaturescheme.csv
|
||||
//
|
||||
//go:embed signature-schemes.csv
|
||||
var signatureSchemesCSV string
|
||||
|
||||
var SignatureSchemeList = parseSignatureSchemesCSV()
|
||||
|
||||
type SignatureScheme any // (uint16 | SignatureSchemeInfo)
|
||||
|
||||
type SignatureSchemeInfo struct {
|
||||
Code uint16 `json:"code"`
|
||||
HexCode string `json:"hex_code"`
|
||||
Name string `json:"name"`
|
||||
Recommended bool `json:"-"`
|
||||
Reference string `json:"-"`
|
||||
}
|
||||
|
||||
func parseSignatureSchemesCSV() map[uint16]SignatureSchemeInfo {
|
||||
signatureSchemes := map[uint16]SignatureSchemeInfo{}
|
||||
r := csv.NewReader(strings.NewReader(signatureSchemesCSV))
|
||||
|
||||
// Skip CSV header.
|
||||
_, err := r.Read()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for {
|
||||
row, err := r.Read()
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
var (
|
||||
val = row[0]
|
||||
desc = row[1]
|
||||
rec = row[2]
|
||||
ref = row[3]
|
||||
)
|
||||
if desc == "Unassigned" {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(desc, "Reserved") && ref != "[RFC8701]" {
|
||||
continue
|
||||
}
|
||||
val = strings.Replace(val, "0x", "", 1)
|
||||
code, err := strconv.ParseUint(val, 16, 16)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
sigScheme := SignatureSchemeInfo{
|
||||
Code: uint16(code),
|
||||
HexCode: fmt.Sprintf("%04X", code),
|
||||
Name: desc,
|
||||
Reference: ref,
|
||||
}
|
||||
if rec == "Y" {
|
||||
sigScheme.Recommended = true
|
||||
}
|
||||
if ref == "[RFC8701]" || isGREASE(sigScheme.Code) {
|
||||
// (We call isGREASE() because the IANA signature scheme registry
|
||||
// doesn't currently include GREASE values).
|
||||
sigScheme.Name = "GREASE"
|
||||
}
|
||||
|
||||
signatureSchemes[sigScheme.Code] = sigScheme
|
||||
}
|
||||
return signatureSchemes
|
||||
}
|
||||
|
||||
func GetSignatureSchemeInfo(sigSchemeCode uint16) SignatureSchemeInfo {
|
||||
info, found := SignatureSchemeList[sigSchemeCode]
|
||||
if !found {
|
||||
info = SignatureSchemeInfo{
|
||||
Code: sigSchemeCode,
|
||||
HexCode: fmt.Sprintf("%04X", sigSchemeCode),
|
||||
}
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func (m *ClientHelloMsg) AddSignatureSchemeInfo() {
|
||||
for i, ext := range m.Extensions {
|
||||
if ext.Code == extensionSignatureAlgorithms ||
|
||||
ext.Code == extensionSignatureAlgorithmsCert {
|
||||
for j, sigAlg := range ext.Data.SupportedSignatureAlgorithms {
|
||||
m.Extensions[i].Data.SupportedSignatureAlgorithms[j] = GetSignatureSchemeInfo(
|
||||
sigAlg.(uint16))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package clienthello
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var TLSVersionList = map[uint16]TLSVersionInfo{
|
||||
768: {Code: 768, HexCode: "0300", Name: "SSL 3.0"},
|
||||
769: {Code: 769, HexCode: "0301", Name: "TLS 1.0"},
|
||||
770: {Code: 770, HexCode: "0302", Name: "TLS 1.1"},
|
||||
771: {Code: 771, HexCode: "0303", Name: "TLS 1.2"},
|
||||
772: {Code: 772, HexCode: "0304", Name: "TLS 1.3"},
|
||||
|
||||
0x0A0A: {Code: 0x0A0A, HexCode: "0A0A", Name: "GREASE"},
|
||||
0x1A1A: {Code: 0x1A1A, HexCode: "1A1A", Name: "GREASE"},
|
||||
0x2A2A: {Code: 0x2A2A, HexCode: "2A2A", Name: "GREASE"},
|
||||
0x3A3A: {Code: 0x3A3A, HexCode: "3A3A", Name: "GREASE"},
|
||||
0x4A4A: {Code: 0x4A4A, HexCode: "4A4A", Name: "GREASE"},
|
||||
0x5A5A: {Code: 0x5A5A, HexCode: "5A5A", Name: "GREASE"},
|
||||
0x6A6A: {Code: 0x6A6A, HexCode: "6A6A", Name: "GREASE"},
|
||||
0x7A7A: {Code: 0x7A7A, HexCode: "7A7A", Name: "GREASE"},
|
||||
0x8A8A: {Code: 0x8A8A, HexCode: "8A8A", Name: "GREASE"},
|
||||
0x9A9A: {Code: 0x9A9A, HexCode: "9A9A", Name: "GREASE"},
|
||||
0xAAAA: {Code: 0xAAAA, HexCode: "AAAA", Name: "GREASE"},
|
||||
0xBABA: {Code: 0xBABA, HexCode: "BABA", Name: "GREASE"},
|
||||
0xCACA: {Code: 0xCACA, HexCode: "CACA", Name: "GREASE"},
|
||||
0xDADA: {Code: 0xDADA, HexCode: "DADA", Name: "GREASE"},
|
||||
0xEAEA: {Code: 0xEAEA, HexCode: "EAEA", Name: "GREASE"},
|
||||
0xFAFA: {Code: 0xFAFA, HexCode: "FAFA", Name: "GREASE"},
|
||||
}
|
||||
|
||||
type TLSVersion any // (uint16 | TLSVersioninfo)
|
||||
|
||||
type TLSVersionInfo struct {
|
||||
Code uint16 `json:"code"`
|
||||
HexCode string `json:"hex_code"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func GetTLSVersionInfo(tlsVersionCode uint16) TLSVersionInfo {
|
||||
info, found := TLSVersionList[tlsVersionCode]
|
||||
if !found {
|
||||
info = TLSVersionInfo{
|
||||
Code: tlsVersionCode,
|
||||
HexCode: fmt.Sprintf("%04X", tlsVersionCode),
|
||||
}
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func (m *ClientHelloMsg) AddTLSVersionInfo() {
|
||||
m.RecordHeaderTLSVersion = GetTLSVersionInfo(m.RecordHeaderTLSVersion.(uint16))
|
||||
m.TLSVersion = GetTLSVersionInfo(m.TLSVersion.(uint16))
|
||||
for i, ext := range m.Extensions {
|
||||
if ext.Code == extensionSupportedVersions {
|
||||
for j, versionCode := range ext.Data.SupportedVersions {
|
||||
m.Extensions[i].Data.SupportedVersions[j] = GetTLSVersionInfo(
|
||||
versionCode.(uint16))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
index.gmi
12
index.gmi
|
@ -1,6 +1,6 @@
|
|||
# TLS Client Hello Mirror
|
||||
|
||||
=> /json/v1 Your browser's TLS Client Hello, reflected as JSON
|
||||
## Your browser's TLS Client Hello, reflected as JSON
|
||||
|
||||
This test:
|
||||
|
||||
|
@ -9,12 +9,14 @@ This test:
|
|||
* supports multiple protocols (currently HTTP and Gemini);
|
||||
* is free as in freedom and trivial to self-host.
|
||||
|
||||
JSON only, for now. The API is largely stable - fields may be added, but existing fields will not be modified or removed. IANA-assigned codes for TLS parameters and extensions are available at:
|
||||
## Endpoints
|
||||
|
||||
=> https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml TLS parameters
|
||||
=> https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml TLS extensions
|
||||
=> /json/v1 json/v1 - basic
|
||||
=> /json/v2 json/v2 - detailed
|
||||
|
||||
Note that these lists do not include draft extensions and GREASE values. Missing values will be documented here as the project evolves.
|
||||
JSON only, for now. The API is largely stable - fields may be added, but existing fields will not be modified or removed. See the documentation for details:
|
||||
|
||||
=> https://tildegit.org/nervuri/client-hello-mirror/src/branch/master/DOC.md API documentation
|
||||
|
||||
_____________________
|
||||
=> https://nervuri.net/ Author: nervuri
|
||||
|
|
19
index.html
19
index.html
|
@ -46,21 +46,20 @@ SPDX-License-Identifier: BSD-3-Clause
|
|||
<body>
|
||||
<main>
|
||||
<h1>TLS Client Hello Mirror</h1>
|
||||
<h3><a href="/json/v1">Your browser's TLS Client Hello, reflected as JSON</a></h3>
|
||||
<h3>Your browser's TLS Client Hello, reflected as JSON</h3>
|
||||
<p>This test:</p>
|
||||
<ul>
|
||||
<li>reflects the complete Client Hello message, preserving the order in which TLS parameters and extensions are sent;</li>
|
||||
<li>can be used to check for TLS privacy pitfalls (<a href="https://svs.informatik.uni-hamburg.de/publications/2018/2018-12-06-Sy-ACSAC-Tracking_Users_across_the_Web_via_TLS_Session_Resumption.pdf">session resumption</a>, <a href="https://tlsfingerprint.io/">TLS fingerprinting</a>, <a href="https://datatracker.ietf.org/doc/html/draft-mathewson-no-gmtunixtime">system time exposure</a>);</li>
|
||||
<li>supports both HTTP and <a href="https://gemini.circumlunar.space/">Gemini</a>;</li>
|
||||
<li>is <a href="https://www.gnu.org/philosophy/free-sw.en.html">free as in freedom</a> and trivial to self-host.</li>
|
||||
<li>reflects the complete Client Hello message, preserving the order in which TLS parameters and extensions are sent;</li>
|
||||
<li>can be used to check for TLS privacy pitfalls (<a href="https://svs.informatik.uni-hamburg.de/publications/2018/2018-12-06-Sy-ACSAC-Tracking_Users_across_the_Web_via_TLS_Session_Resumption.pdf">session resumption</a>, <a href="https://tlsfingerprint.io/">TLS fingerprinting</a>, <a href="https://datatracker.ietf.org/doc/html/draft-mathewson-no-gmtunixtime">system time exposure</a>);</li>
|
||||
<li>supports both HTTP and <a href="https://gemini.circumlunar.space/">Gemini</a>;</li>
|
||||
<li>is <a href="https://www.gnu.org/philosophy/free-sw.en.html">free as in freedom</a> and trivial to self-host.</li>
|
||||
</ul>
|
||||
<p>JSON only, for now, but a UI is on <a href="https://tildegit.org/nervuri/client-hello-mirror#roadmap">the roadmap</a>.</p>
|
||||
<p>The API is largely stable - fields may be added, but existing fields will not be modified or removed. IANA-assigned codes for TLS parameters and extensions are documented at:</p>
|
||||
<h3>Endpoints</h3>
|
||||
<ul>
|
||||
<li><a href="https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml">TLS parameters</a></li>
|
||||
<li><a href="https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml">TLS extensions</a></li>
|
||||
<li><a href="/json/v1">json/v1 - basic</a></li>
|
||||
<li><a href="/json/v2">json/v2 - detailed</a></li>
|
||||
</ul>
|
||||
<p>Note that these lists do not include draft extensions and <a href="https://datatracker.ietf.org/doc/html/rfc8701">GREASE</a> values. Missing values will be documented here as the project evolves.</p>
|
||||
<p>JSON only, for now. The API is largely stable - fields may be added, but existing fields will not be modified or removed. See <a href="https://tildegit.org/nervuri/client-hello-mirror/src/branch/master/DOC.md">the documentation</a> for details.</p>
|
||||
</main>
|
||||
<hr/>
|
||||
<footer>
|
||||
|
|
|
@ -28,6 +28,8 @@ const (
|
|||
headMethod = 2
|
||||
)
|
||||
|
||||
var ErrNotSupported = errors.New("Unsupported protocol or HTTP method")
|
||||
|
||||
// Get request information from the first line of the request.
|
||||
func getRequestInfo(firstLine string) (req request, err error) {
|
||||
if strings.HasPrefix(firstLine, "gemini://") {
|
||||
|
@ -43,7 +45,7 @@ func getRequestInfo(firstLine string) (req request, err error) {
|
|||
} else if strings.HasPrefix(firstLine, "HEAD ") {
|
||||
req.HTTPMethod = headMethod
|
||||
} else {
|
||||
err = errors.New("Unsupported protocol or HTTP method")
|
||||
err = ErrNotSupported
|
||||
return
|
||||
}
|
||||
if req.HTTPMethod != 0 {
|
||||
|
|
22
server.go
22
server.go
|
@ -16,18 +16,19 @@ import (
|
|||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"tildegit.org/nervuri/client-hello-mirror/clienthello"
|
||||
"time"
|
||||
|
||||
"tildegit.org/nervuri/client-hello-mirror/clienthello"
|
||||
)
|
||||
|
||||
const readTimeout = 10 // seconds
|
||||
const writeTimeout = 10 // seconds
|
||||
|
||||
type tlsConnectionInfo struct {
|
||||
TlsVersion uint16 `json:"tls_version"`
|
||||
CipherSuite uint16 `json:"cipher_suite"`
|
||||
SessionResumed bool `json:"session_resumed"`
|
||||
NegotiatedProtocol string `json:"alpn_negotiated_protocol"` // ALPN
|
||||
TLSVersion clienthello.TLSVersion `json:"tls_version"`
|
||||
CipherSuite clienthello.CipherSuite `json:"cipher_suite"`
|
||||
SessionResumed bool `json:"session_resumed"`
|
||||
NegotiatedProtocol string `json:"alpn_negotiated_protocol"` // ALPN
|
||||
}
|
||||
|
||||
// Connection wrapper that enables exposing the Client Hello to the
|
||||
|
@ -161,16 +162,23 @@ func requestHandler(conn *tls.Conn, rawClientHello []byte) {
|
|||
} else if req.Protocol == geminiProtocol {
|
||||
resp.Body = gemtext
|
||||
}
|
||||
} else if req.Path == "/json/v1" {
|
||||
} else if req.Path == "/json/v1" || req.Path == "/json/v2" {
|
||||
if req.Protocol == httpProtocol {
|
||||
resp.Headers["Content-Type"] = "application/json"
|
||||
resp.DisableCaching()
|
||||
} else if req.Protocol == geminiProtocol {
|
||||
resp.StatusLine = "20 application/json"
|
||||
}
|
||||
if req.Path == "/json/v2" {
|
||||
clientHelloMsg.AddInfo()
|
||||
tlsConnInfo.TLSVersion = clienthello.GetTLSVersionInfo(
|
||||
tlsConnInfo.TLSVersion.(uint16))
|
||||
tlsConnInfo.CipherSuite = clienthello.GetCipherSuiteInfo(
|
||||
tlsConnInfo.CipherSuite.(uint16))
|
||||
}
|
||||
output := struct {
|
||||
ClientHello clienthello.ClientHelloMsg `json:"client_hello"`
|
||||
TlsConnectionInfo tlsConnectionInfo `json:"connection_info"`
|
||||
TLSConnectionInfo tlsConnectionInfo `json:"connection_info"`
|
||||
}{
|
||||
clientHelloMsg,
|
||||
tlsConnInfo,
|
||||
|
|
Loading…
Reference in New Issue