summaryrefslogtreecommitdiffstats
path: root/rust/vendor/tls-parser
diff options
context:
space:
mode:
Diffstat (limited to 'rust/vendor/tls-parser')
-rw-r--r--rust/vendor/tls-parser/.cargo-checksum.json1
-rw-r--r--rust/vendor/tls-parser/Cargo.toml66
-rw-r--r--rust/vendor/tls-parser/LICENSE-APACHE201
-rw-r--r--rust/vendor/tls-parser/LICENSE-MIT25
-rw-r--r--rust/vendor/tls-parser/benches/bench_dh.rs50
-rw-r--r--rust/vendor/tls-parser/benches/bench_handshake.rs383
-rw-r--r--rust/vendor/tls-parser/build.rs91
-rwxr-xr-xrust/vendor/tls-parser/scripts/extract-iana-ciphers.py180
-rw-r--r--rust/vendor/tls-parser/scripts/tls-ciphersuites.txt343
-rw-r--r--rust/vendor/tls-parser/src/certificate_transparency.rs111
-rw-r--r--rust/vendor/tls-parser/src/dtls.rs314
-rw-r--r--rust/vendor/tls-parser/src/lib.rs175
-rw-r--r--rust/vendor/tls-parser/src/tls.rs977
-rw-r--r--rust/vendor/tls-parser/src/tls_alert.rs101
-rw-r--r--rust/vendor/tls-parser/src/tls_ciphers.rs156
-rw-r--r--rust/vendor/tls-parser/src/tls_debug.rs289
-rw-r--r--rust/vendor/tls-parser/src/tls_dh.rs23
-rw-r--r--rust/vendor/tls-parser/src/tls_ec.rs200
-rw-r--r--rust/vendor/tls-parser/src/tls_extensions.rs747
-rw-r--r--rust/vendor/tls-parser/src/tls_serialize.rs568
-rw-r--r--rust/vendor/tls-parser/src/tls_sign_hash.rs151
-rw-r--r--rust/vendor/tls-parser/src/tls_states.rs132
-rw-r--r--rust/vendor/tls-parser/tests/certificate_transparency.rs95
-rw-r--r--rust/vendor/tls-parser/tests/tls_dh.rs145
-rw-r--r--rust/vendor/tls-parser/tests/tls_extensions.rs209
-rw-r--r--rust/vendor/tls-parser/tests/tls_handshake.rs817
-rw-r--r--rust/vendor/tls-parser/tests/tls_tls13.rs122
27 files changed, 6672 insertions, 0 deletions
diff --git a/rust/vendor/tls-parser/.cargo-checksum.json b/rust/vendor/tls-parser/.cargo-checksum.json
new file mode 100644
index 0000000..e48e043
--- /dev/null
+++ b/rust/vendor/tls-parser/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"ddf1cde883d0811b8cf444820d52aeda43ff231d77e701abee7fe6212a8cecd0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"a5c61b93b6ee1d104af9920cf020ff3c7efe818e31fe562c72261847a728f513","benches/bench_dh.rs":"27cd2538b0680ff1fc2efdef6bf3b3545105f8239c75be3cbb05db9c61b316f9","benches/bench_handshake.rs":"acb78401fdd785bf59c3353d6a786c67e7a1a653616c87c1750b53b527dcd63f","build.rs":"44d122debceaa91c6e74d589a5c730ec1cbdda1172f88ba9faf9744fc008339d","scripts/extract-iana-ciphers.py":"34a47d560357498b1ac2bf6e142205ed96bad2418ef842872949a856269b9d50","scripts/tls-ciphersuites.txt":"6921d59de103832394dafe58a3b4a735d14cfbc96c642bd62bf44a8bc4485e20","src/certificate_transparency.rs":"e134d64c2ddaca87f336db9d8fedb8eb2b1698cdef6a9a942e0596d0971f2ed2","src/dtls.rs":"98363e9eb56c18e4f44c389c6e8a124e08f0b8bf67703bd6ee3277f5e8093632","src/lib.rs":"535bd75230d58679e2c5c3098fcf061e43313291c3315eeff0462ccca68a709f","src/tls.rs":"441a9aad8811ce4382955ec930b4ff65b19d22229ecd41d543f08b08be6db954","src/tls_alert.rs":"ead681e225d4342a3db401ce0b1cdbd42bf3065be195144d552904b0c83a32a7","src/tls_ciphers.rs":"dc005009a07c1d6c862df21bafa4bd34c4207aa1cb5aebe5c8c613d1cbbda6ff","src/tls_debug.rs":"45161ff3696308731473f234524bfa46250a397b53aab783a7761c38f7136f37","src/tls_dh.rs":"344ab625d2c4a9e42e221bc443a4ee0d055b2e1c109f94389d5fb6534de310ad","src/tls_ec.rs":"8959c3c38d8ccbb7ed0c9fa2ae4a11540935b894c36d54cfc3e56b2720c45c54","src/tls_extensions.rs":"ed31e26d044dc17b4a17210686481fd7ffa0dbd4e5ca76694f471dccb540aed8","src/tls_serialize.rs":"59a14e010c4a560098246980e53c6599670a3c08ea1660df7b0f357537350bed","src/tls_sign_hash.rs":"97c4c94376866ab2ccc365620c2d3f5ddbbe3a95e1fea08fa98b057877ddeae4","src/tls_states.rs":"6bb34c64661f2af36001cfc5ef76738119bee818d8e8a4d117312e665bdb3cb9","tests/certificate_transparency.rs":"c69fc77af11f4f52faab4eda17946f80a4d6f2e1eab3fb2e6c666d4186d4608b","tests/tls_dh.rs":"0357bb0d8f473912617ebf6a264c41caae31eca6297d5546964a3a8cbaedf3ae","tests/tls_extensions.rs":"66e464934926311b730ab4fd607b4100ee994848f15dbe2b5114b0dd814be18b","tests/tls_handshake.rs":"50cd129d53e236d7486b63b0b498728ff7cb638fa27125ad2f2a8f0846d0e776","tests/tls_tls13.rs":"0d9a7189e12aa3cfa7ed8308bb3963cf30a0fa4bd1fa6c567c58eaf4600f4103"},"package":"409206e2de64edbf7ea99a44ac31680daf9ef1a57895fb3c5bd738a903691be0"} \ No newline at end of file
diff --git a/rust/vendor/tls-parser/Cargo.toml b/rust/vendor/tls-parser/Cargo.toml
new file mode 100644
index 0000000..6b9b48e
--- /dev/null
+++ b/rust/vendor/tls-parser/Cargo.toml
@@ -0,0 +1,66 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "tls-parser"
+version = "0.11.0"
+authors = ["Pierre Chifflier <chifflier@wzdftpd.net>"]
+build = "build.rs"
+include = ["LICENSE-*", ".gitignore", ".travis.yml", "Cargo.toml", "benches/*.rs", "build.rs", "src/*.rs", "tests/*.rs", "scripts/tls-ciphersuites.txt", "scripts/extract-iana-ciphers.py"]
+description = "Parser for the TLS protocol"
+homepage = "https://github.com/rusticata/tls-parser"
+documentation = "https://docs.rs/tls-parser"
+readme = "README.md"
+keywords = ["TLS", "SSL", "protocol", "parser", "nom"]
+categories = ["network-programming", "parser-implementations"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/rusticata/tls-parser.git"
+
+[lib]
+name = "tls_parser"
+[dependencies.cookie-factory]
+version = "0.3"
+optional = true
+
+[dependencies.enum_primitive]
+version = "^0.1"
+
+[dependencies.nom]
+version = "7.0"
+
+[dependencies.nom-derive]
+version = "0.10"
+
+[dependencies.phf]
+version = "0.10"
+
+[dependencies.rusticata-macros]
+version = "4.0"
+[dev-dependencies.clap]
+version = "~2.33"
+default-features = false
+
+[dev-dependencies.hex-literal]
+version = "0.3"
+
+[dev-dependencies.pretty_assertions]
+version = "0.7"
+[build-dependencies.phf_codegen]
+version = "0.10"
+
+[features]
+default = ["std"]
+serialize = ["cookie-factory"]
+std = []
+unstable = []
+[badges.travis-ci]
+repository = "rusticata/tls-parser"
diff --git a/rust/vendor/tls-parser/LICENSE-APACHE b/rust/vendor/tls-parser/LICENSE-APACHE
new file mode 100644
index 0000000..16fe87b
--- /dev/null
+++ b/rust/vendor/tls-parser/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/rust/vendor/tls-parser/LICENSE-MIT b/rust/vendor/tls-parser/LICENSE-MIT
new file mode 100644
index 0000000..290e7b9
--- /dev/null
+++ b/rust/vendor/tls-parser/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2017 Pierre Chifflier
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/rust/vendor/tls-parser/benches/bench_dh.rs b/rust/vendor/tls-parser/benches/bench_dh.rs
new file mode 100644
index 0000000..2dbe98f
--- /dev/null
+++ b/rust/vendor/tls-parser/benches/bench_dh.rs
@@ -0,0 +1,50 @@
+#![cfg(all(feature = "unstable", test))]
+#![feature(test)]
+
+extern crate test;
+
+#[macro_use]
+extern crate nom;
+extern crate tls_parser;
+
+mod tls_dh {
+ use test::Bencher;
+ use tls_parser::*;
+
+ #[rustfmt::skip]
+ static ECDHE_PARAMS: &[u8] = &[
+ 0x03, 0x00, 0x19, 0x85, 0x04, 0x01, 0xd1, 0x50, 0x12, 0xf4, 0xc4, 0xcf, 0xd4, 0xc2, 0x1f, 0xe8,
+ 0xf6, 0x85, 0xdc, 0xde, 0x0b, 0xeb, 0x3c, 0x0d, 0x0f, 0x97, 0x29, 0x36, 0x63, 0xc6, 0xc1, 0x3b,
+ 0xfd, 0x38, 0xce, 0xde, 0x43, 0x7f, 0x7d, 0x57, 0x64, 0x54, 0x6f, 0x89, 0x3c, 0xe7, 0x5e, 0x28,
+ 0x9e, 0x9d, 0x24, 0xca, 0x07, 0x63, 0xd5, 0x03, 0x30, 0x8b, 0xd8, 0x1a, 0xae, 0xb6, 0xa8, 0x5f,
+ 0x10, 0x87, 0x81, 0x29, 0x1b, 0xef, 0xbd, 0x00, 0xeb, 0x29, 0x37, 0xb3, 0xc3, 0xda, 0x8e, 0xad,
+ 0xf3, 0x9c, 0x10, 0xe3, 0x93, 0xeb, 0x0a, 0x53, 0x14, 0xea, 0x3c, 0x05, 0xb7, 0xc1, 0x6b, 0x79,
+ 0xca, 0xfc, 0x9a, 0x5b, 0xc3, 0xaf, 0xf2, 0xdd, 0x9f, 0xdd, 0x07, 0xf5, 0x07, 0xef, 0xb4, 0x24,
+ 0xac, 0xdb, 0xd2, 0x0d, 0x65, 0x37, 0x96, 0xa0, 0x15, 0xef, 0x7c, 0x6d, 0x66, 0x63, 0x0d, 0x41,
+ 0x1d, 0xd7, 0x90, 0x05, 0x66, 0xcf, 0x79, 0x0c, 0x03, 0x02, 0x01, 0x01, 0x00, 0x7c, 0xa7, 0x5f,
+ 0x73, 0x77, 0x2c, 0x92, 0x4c, 0xe4, 0xa7, 0x67, 0x86, 0x76, 0xf2, 0xa3, 0xf8, 0xd1, 0x9d, 0xca,
+ 0x4f, 0x71, 0xd1, 0x67, 0xf4, 0xbe, 0x7e, 0xb3, 0x60, 0xc4, 0xf1, 0x6e, 0x90, 0x22, 0x97, 0xe9,
+ 0xc2, 0x43, 0xc9, 0xfb, 0x46, 0x21, 0xd4, 0xe9, 0xed, 0xdc, 0x46, 0x5b, 0x3e, 0x4c, 0xfb, 0xf2,
+ 0xeb, 0x3f, 0x09, 0x4e, 0x59, 0x5f, 0x6f, 0x60, 0x50, 0x8a, 0x80, 0x50, 0xa7, 0xc3, 0xb9, 0xf0,
+ 0xd1, 0x80, 0xb0, 0x1b, 0x11, 0x53, 0xe4, 0xac, 0x45, 0xa8, 0x75, 0x59, 0x55, 0x1a, 0x20, 0xa5,
+ 0xbb, 0x23, 0xb6, 0x1c, 0x39, 0xa8, 0x4e, 0x62, 0x57, 0xef, 0x4f, 0x11, 0xce, 0x64, 0x87, 0x9b,
+ 0x5a, 0xb8, 0x06, 0xf1, 0x62, 0x63, 0x3d, 0x13, 0x46, 0x72, 0x79, 0x7e, 0x65, 0x5c, 0xb4, 0x0a,
+ 0xe3, 0x63, 0x13, 0x05, 0xc9, 0xaa, 0xc3, 0x93, 0x9b, 0x69, 0x37, 0x04, 0xa6, 0x7b, 0x69, 0xa9,
+ 0x72, 0x67, 0x32, 0x9d, 0xc9, 0x53, 0x05, 0xe5, 0x18, 0x00, 0x73, 0xcb, 0x40, 0xd8, 0x86, 0x81,
+ 0x01, 0x78, 0x36, 0x8f, 0x62, 0x94, 0xb4, 0x88, 0x27, 0xdb, 0x8e, 0xe4, 0x76, 0x56, 0x1d, 0xac,
+ 0x7d, 0x36, 0x4c, 0xb4, 0xad, 0x4c, 0xe0, 0x21, 0x1f, 0xd5, 0x2d, 0x30, 0xa0, 0x78, 0xba, 0x28,
+ 0x0b, 0xb4, 0x6d, 0xf1, 0x95, 0x41, 0x11, 0xdb, 0x64, 0xaf, 0x11, 0xa2, 0x9b, 0x45, 0x07, 0x42,
+ 0x95, 0xf1, 0xe4, 0x0a, 0x16, 0x0c, 0x7f, 0xa7, 0x96, 0xc1, 0x91, 0xf0, 0x7c, 0xf7, 0x67, 0xe6,
+ 0x1c, 0xbd, 0x1d, 0xcb, 0xbc, 0x42, 0x2a, 0x47, 0x35, 0x28, 0x96, 0xc3, 0x08, 0x48, 0x7d, 0xe9,
+ 0xf1, 0x42, 0x00, 0xee, 0xd5, 0x0e, 0xd4, 0x08, 0xd6, 0x34, 0x15, 0xd6, 0x7c, 0x4b, 0xc5, 0x23,
+ 0xf4, 0x8c, 0xfa, 0x70, 0xd8, 0x60, 0x46, 0xd2, 0xa3, 0xba, 0x75, 0xa4, 0x8f
+ ];
+
+ #[bench]
+ fn bench_tls_ecdhe_params(b: &mut Bencher) {
+ let bytes = ECDHE_PARAMS;
+ b.iter(|| {
+ let _ = pair!(bytes, parse_ecdh_params, parse_digitally_signed);
+ })
+ }
+} // mod tls_dh
diff --git a/rust/vendor/tls-parser/benches/bench_handshake.rs b/rust/vendor/tls-parser/benches/bench_handshake.rs
new file mode 100644
index 0000000..0323062
--- /dev/null
+++ b/rust/vendor/tls-parser/benches/bench_handshake.rs
@@ -0,0 +1,383 @@
+#![cfg(feature = "unstable")]
+#![cfg(all(feature = "unstable", test))]
+#![feature(test)]
+
+extern crate test;
+
+extern crate nom;
+extern crate tls_parser;
+
+mod tls_handshake {
+ use test::Bencher;
+ use tls_parser::*;
+
+ #[rustfmt::skip]
+ static CH: &[u8] = &[
+ 0x16, 0x03, 0x01, 0x01, 0x2c, 0x01, 0x00, 0x01, 0x28, 0x03, 0x03, 0xb2,
+ 0x9d, 0xd7, 0x87, 0xff, 0x21, 0xeb, 0x04, 0xc8, 0xa5, 0x38, 0x39, 0x9a,
+ 0xcf, 0xb7, 0xa3, 0x82, 0x1f, 0x82, 0x6c, 0x49, 0xbc, 0x8b, 0xb8, 0xa9,
+ 0x03, 0x0a, 0x2d, 0xce, 0x38, 0x0b, 0xf4, 0x00, 0x00, 0xaa, 0xc0, 0x30,
+ 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0xa5,
+ 0x00, 0xa3, 0x00, 0xa1, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x6a, 0x00, 0x69,
+ 0x00, 0x68, 0x00, 0x39, 0x00, 0x38, 0x00, 0x37, 0x00, 0x36, 0x00, 0x88,
+ 0x00, 0x87, 0x00, 0x86, 0x00, 0x85, 0xc0, 0x32, 0xc0, 0x2e, 0xc0, 0x2a,
+ 0xc0, 0x26, 0xc0, 0x0f, 0xc0, 0x05, 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35,
+ 0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x13,
+ 0xc0, 0x09, 0x00, 0xa4, 0x00, 0xa2, 0x00, 0xa0, 0x00, 0x9e, 0x00, 0x67,
+ 0x00, 0x40, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x33, 0x00, 0x32, 0x00, 0x31,
+ 0x00, 0x30, 0x00, 0x9a, 0x00, 0x99, 0x00, 0x98, 0x00, 0x97, 0x00, 0x45,
+ 0x00, 0x44, 0x00, 0x43, 0x00, 0x42, 0xc0, 0x31, 0xc0, 0x2d, 0xc0, 0x29,
+ 0xc0, 0x25, 0xc0, 0x0e, 0xc0, 0x04, 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f,
+ 0x00, 0x96, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0xc0, 0x0c, 0xc0, 0x02,
+ 0x00, 0x05, 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x13,
+ 0x00, 0x10, 0x00, 0x0d, 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a, 0x00, 0xff,
+ 0x01, 0x00, 0x00, 0x55, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01, 0x02,
+ 0x00, 0x0a, 0x00, 0x1c, 0x00, 0x1a, 0x00, 0x17, 0x00, 0x19, 0x00, 0x1c,
+ 0x00, 0x1b, 0x00, 0x18, 0x00, 0x1a, 0x00, 0x16, 0x00, 0x0e, 0x00, 0x0d,
+ 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x23, 0x00, 0x00,
+ 0x00, 0x0d, 0x00, 0x20, 0x00, 0x1e, 0x06, 0x01, 0x06, 0x02, 0x06, 0x03,
+ 0x05, 0x01, 0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03,
+ 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,
+ 0x00, 0x0f, 0x00, 0x01, 0x01
+ ];
+
+ #[bench]
+ fn bench_tls_record_clienthello(b: &mut Bencher) {
+ b.iter(|| {
+ let _ = parse_tls_plaintext(&CH);
+ })
+ }
+
+ // tls response, composed of 4 records:
+ // - Server Hello
+ // - Server Certificate
+ // - Server Key Exchange
+ // - Server Hello Done
+ #[rustfmt::skip]
+ static SERVER_REPLY1: &[u8] = &[
+ 0x16, 0x03, 0x03, 0x00, 0x3b, 0x02, 0x00, 0x00, 0x37, 0x03, 0x03, 0x57,
+ 0xc4, 0x57, 0xda, 0x9c, 0xd3, 0x24, 0x6d, 0x9d, 0x02, 0x26, 0xa2, 0xe5,
+ 0x9a, 0xe8, 0xa5, 0x6f, 0x40, 0xad, 0x94, 0x30, 0xba, 0x49, 0x05, 0x3a,
+ 0x1e, 0x1b, 0xe1, 0x94, 0xa1, 0xba, 0x41, 0x00, 0xc0, 0x2f, 0x00, 0x00,
+ 0x0f, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0b,
+ 0x00, 0x02, 0x01, 0x00, 0x16, 0x03, 0x03, 0x0c, 0x09, 0x0b, 0x00, 0x0c,
+ 0x05, 0x00, 0x0c, 0x02, 0x00, 0x04, 0x84, 0x30, 0x82, 0x04, 0x80, 0x30,
+ 0x82, 0x03, 0x68, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x52, 0x1a,
+ 0x61, 0xda, 0x68, 0xb6, 0xe6, 0x35, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x49, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53,
+ 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x25, 0x30,
+ 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20,
+ 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x38, 0x31, 0x37, 0x31, 0x38,
+ 0x34, 0x39, 0x30, 0x31, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x31, 0x30,
+ 0x39, 0x31, 0x38, 0x32, 0x39, 0x30, 0x30, 0x5a, 0x30, 0x68, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61,
+ 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 0x30, 0x14,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d, 0x6f, 0x75, 0x6e, 0x74,
+ 0x61, 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x0e, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82,
+ 0x01, 0x01, 0x00, 0x9b, 0x5b, 0x36, 0xcc, 0xce, 0x8c, 0x39, 0x86, 0xbd,
+ 0x05, 0x2f, 0xc3, 0xff, 0x4c, 0x59, 0xa8, 0xfc, 0xe4, 0x6e, 0x0f, 0xc6,
+ 0xbf, 0x23, 0xf6, 0x35, 0xc5, 0x3b, 0xcc, 0xc9, 0x61, 0x2f, 0x60, 0x11,
+ 0x9b, 0x7a, 0x44, 0xd2, 0xd0, 0xd9, 0x62, 0x11, 0x09, 0xbe, 0x08, 0x53,
+ 0x24, 0x73, 0xd9, 0x5f, 0x5e, 0xb0, 0x6f, 0x05, 0x3f, 0x53, 0xa3, 0x2d,
+ 0x98, 0xa4, 0xf4, 0xaf, 0x23, 0x25, 0xb8, 0x80, 0xbc, 0xcc, 0xde, 0xa2,
+ 0x56, 0xcb, 0x6f, 0x9d, 0x1a, 0xda, 0xa5, 0xbe, 0xb0, 0x8a, 0xdc, 0xcf,
+ 0x30, 0xef, 0xe0, 0x68, 0x97, 0xc5, 0x70, 0xad, 0xcf, 0x10, 0x5b, 0xb6,
+ 0x92, 0x98, 0x61, 0x57, 0x3d, 0xbf, 0x3f, 0xd0, 0x5d, 0xbc, 0x76, 0x23,
+ 0xc8, 0xce, 0x35, 0x6d, 0x25, 0x1f, 0x11, 0x5a, 0x4b, 0x76, 0x36, 0xca,
+ 0xd4, 0x57, 0x7e, 0x95, 0x7f, 0x78, 0xfb, 0x2c, 0xe0, 0x9a, 0xbf, 0x64,
+ 0xc6, 0x43, 0x7b, 0xcd, 0xfa, 0x0e, 0xaa, 0x4f, 0x6a, 0xda, 0x04, 0xa4,
+ 0xf5, 0xfa, 0x2d, 0xea, 0xac, 0xc3, 0xa7, 0xf4, 0xd3, 0x7c, 0x57, 0xd4,
+ 0xb8, 0x2c, 0xcb, 0xe0, 0xd5, 0x26, 0x3b, 0x2d, 0x64, 0x0d, 0x20, 0x5a,
+ 0xd5, 0xe4, 0x1a, 0x6e, 0x3a, 0x6a, 0x23, 0xb1, 0x0a, 0xc6, 0x33, 0xee,
+ 0x49, 0x66, 0x13, 0x38, 0x58, 0x76, 0x53, 0x84, 0x4a, 0x8a, 0xaa, 0x77,
+ 0x8e, 0xa8, 0x38, 0xfb, 0xe9, 0x4d, 0xd0, 0x02, 0xf9, 0x7b, 0xf3, 0x67,
+ 0x94, 0xe0, 0x58, 0x9e, 0x04, 0xc1, 0x3b, 0xd8, 0x2b, 0x89, 0x5f, 0x57,
+ 0xf3, 0xb5, 0xf3, 0x41, 0x63, 0x7a, 0x32, 0x98, 0x5e, 0x18, 0x29, 0x04,
+ 0xb7, 0x64, 0xbe, 0x91, 0xf9, 0x15, 0xf7, 0x34, 0x23, 0x0f, 0x4d, 0xd1,
+ 0xeb, 0x80, 0xe9, 0xad, 0xb3, 0x65, 0xc1, 0xcd, 0x7e, 0x68, 0x3f, 0x9b,
+ 0x0c, 0x6d, 0xb2, 0xbf, 0x16, 0x11, 0x21, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0xa3, 0x82, 0x01, 0x4b, 0x30, 0x82, 0x01, 0x47, 0x30, 0x1d, 0x06, 0x03,
+ 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01,
+ 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x03, 0x02, 0x30, 0x19, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x12,
+ 0x30, 0x10, 0x82, 0x0e, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x68, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x5c, 0x30, 0x5a, 0x30, 0x2b,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x1f,
+ 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x47, 0x49,
+ 0x41, 0x47, 0x32, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x2b, 0x06, 0x08, 0x2b,
+ 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x31,
+ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
+ 0x6f, 0x63, 0x73, 0x70, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04,
+ 0x16, 0x04, 0x14, 0x2e, 0x67, 0x92, 0x22, 0x0f, 0xd3, 0xd5, 0xd1, 0xd6,
+ 0x0a, 0x21, 0xf5, 0x3e, 0x2b, 0xe7, 0x87, 0xbe, 0xaf, 0x37, 0x9b, 0x30,
+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30,
+ 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
+ 0x80, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b, 0xbc, 0xf6, 0x68, 0xb5, 0x76,
+ 0xf5, 0x81, 0xb6, 0xbb, 0x62, 0x1a, 0xba, 0x5a, 0x81, 0x2f, 0x30, 0x21,
+ 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x1a, 0x30, 0x18, 0x30, 0x0c, 0x06,
+ 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01, 0x30,
+ 0x08, 0x06, 0x06, 0x67, 0x81, 0x0c, 0x01, 0x02, 0x02, 0x30, 0x30, 0x06,
+ 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x29, 0x30, 0x27, 0x30, 0x25, 0xa0, 0x23,
+ 0xa0, 0x21, 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70,
+ 0x6b, 0x69, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32, 0x2e, 0x63, 0x72, 0x6c, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+ 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x7d, 0x0e, 0x9e, 0x7b, 0xf0,
+ 0x81, 0xd6, 0x19, 0xa5, 0xc1, 0xe3, 0xd4, 0x16, 0xad, 0x17, 0x74, 0x76,
+ 0x80, 0x97, 0x9c, 0x96, 0x7b, 0xfb, 0x8e, 0x3a, 0x12, 0x14, 0x25, 0x48,
+ 0xb9, 0xed, 0x46, 0xc9, 0x07, 0xc6, 0xd9, 0xfd, 0x06, 0xba, 0x9f, 0x66,
+ 0xd6, 0x1c, 0xe4, 0xbb, 0xcb, 0x76, 0x44, 0x95, 0x31, 0x76, 0x4c, 0xfb,
+ 0xb5, 0xad, 0xc7, 0xf0, 0x6a, 0xfa, 0x30, 0xc3, 0x58, 0xa1, 0x8b, 0xcc,
+ 0xe2, 0x70, 0xbb, 0x8a, 0x78, 0x5e, 0x41, 0x60, 0x1e, 0xda, 0x69, 0xc3,
+ 0xcb, 0x9f, 0xa2, 0x10, 0xff, 0x20, 0xfc, 0xa4, 0x35, 0xdb, 0x32, 0xcb,
+ 0x26, 0xba, 0xc0, 0xcf, 0x3f, 0x5c, 0x86, 0x78, 0x2c, 0xaa, 0x73, 0x39,
+ 0xf9, 0x8c, 0xfd, 0xa6, 0x9a, 0x8e, 0x3f, 0x5d, 0x7d, 0x8c, 0x7c, 0x3a,
+ 0xe7, 0xbe, 0x69, 0x73, 0xa8, 0x06, 0x5d, 0x56, 0xe3, 0xe2, 0x80, 0x0d,
+ 0x99, 0xcc, 0x4d, 0x5f, 0x7e, 0xfb, 0x62, 0xd8, 0xcf, 0x55, 0x2d, 0xbc,
+ 0x9f, 0xef, 0xa7, 0xe6, 0x46, 0xda, 0xc9, 0x66, 0x07, 0x0e, 0x13, 0x4d,
+ 0x61, 0xb3, 0x85, 0xf3, 0x72, 0x6d, 0x41, 0xfe, 0x7b, 0xaa, 0xe7, 0xaf,
+ 0xff, 0x61, 0xd9, 0xc6, 0x6c, 0x84, 0x6c, 0x1a, 0x9e, 0xda, 0x86, 0x15,
+ 0xbc, 0x2a, 0xae, 0x84, 0x14, 0x94, 0x67, 0x95, 0xc4, 0xda, 0x35, 0x29,
+ 0x8e, 0x80, 0x23, 0xc0, 0x4a, 0xdd, 0x0e, 0xb3, 0xb1, 0x7d, 0xc7, 0x3d,
+ 0xea, 0x2c, 0x41, 0xb2, 0xed, 0xb4, 0x8b, 0x65, 0xd3, 0x62, 0x81, 0x0a,
+ 0x25, 0x0c, 0x3b, 0xc9, 0x11, 0xa2, 0x50, 0x1f, 0xd0, 0xe9, 0x37, 0x9f,
+ 0xa0, 0x7a, 0x34, 0x01, 0xdf, 0x32, 0x58, 0x3b, 0xf5, 0x4b, 0xd8, 0xab,
+ 0x11, 0x5a, 0x9a, 0x1b, 0x83, 0x43, 0x06, 0xf4, 0x40, 0x1e, 0x5b, 0x92,
+ 0xe8, 0x94, 0x0a, 0xbc, 0x57, 0x2f, 0x19, 0x69, 0xc6, 0xd2, 0x8b, 0x00,
+ 0x03, 0xf4, 0x30, 0x82, 0x03, 0xf0, 0x30, 0x82, 0x02, 0xd8, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x03, 0x02, 0x3a, 0x92, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30,
+ 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x0d, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x49, 0x6e,
+ 0x63, 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+ 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6c,
+ 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31,
+ 0x35, 0x30, 0x34, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
+ 0x17, 0x0d, 0x31, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39,
+ 0x35, 0x39, 0x5a, 0x30, 0x49, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20,
+ 0x49, 0x6e, 0x63, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74,
+ 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
+ 0x69, 0x74, 0x79, 0x20, 0x47, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82,
+ 0x01, 0x01, 0x00, 0x9c, 0x2a, 0x04, 0x77, 0x5c, 0xd8, 0x50, 0x91, 0x3a,
+ 0x06, 0xa3, 0x82, 0xe0, 0xd8, 0x50, 0x48, 0xbc, 0x89, 0x3f, 0xf1, 0x19,
+ 0x70, 0x1a, 0x88, 0x46, 0x7e, 0xe0, 0x8f, 0xc5, 0xf1, 0x89, 0xce, 0x21,
+ 0xee, 0x5a, 0xfe, 0x61, 0x0d, 0xb7, 0x32, 0x44, 0x89, 0xa0, 0x74, 0x0b,
+ 0x53, 0x4f, 0x55, 0xa4, 0xce, 0x82, 0x62, 0x95, 0xee, 0xeb, 0x59, 0x5f,
+ 0xc6, 0xe1, 0x05, 0x80, 0x12, 0xc4, 0x5e, 0x94, 0x3f, 0xbc, 0x5b, 0x48,
+ 0x38, 0xf4, 0x53, 0xf7, 0x24, 0xe6, 0xfb, 0x91, 0xe9, 0x15, 0xc4, 0xcf,
+ 0xf4, 0x53, 0x0d, 0xf4, 0x4a, 0xfc, 0x9f, 0x54, 0xde, 0x7d, 0xbe, 0xa0,
+ 0x6b, 0x6f, 0x87, 0xc0, 0xd0, 0x50, 0x1f, 0x28, 0x30, 0x03, 0x40, 0xda,
+ 0x08, 0x73, 0x51, 0x6c, 0x7f, 0xff, 0x3a, 0x3c, 0xa7, 0x37, 0x06, 0x8e,
+ 0xbd, 0x4b, 0x11, 0x04, 0xeb, 0x7d, 0x24, 0xde, 0xe6, 0xf9, 0xfc, 0x31,
+ 0x71, 0xfb, 0x94, 0xd5, 0x60, 0xf3, 0x2e, 0x4a, 0xaf, 0x42, 0xd2, 0xcb,
+ 0xea, 0xc4, 0x6a, 0x1a, 0xb2, 0xcc, 0x53, 0xdd, 0x15, 0x4b, 0x8b, 0x1f,
+ 0xc8, 0x19, 0x61, 0x1f, 0xcd, 0x9d, 0xa8, 0x3e, 0x63, 0x2b, 0x84, 0x35,
+ 0x69, 0x65, 0x84, 0xc8, 0x19, 0xc5, 0x46, 0x22, 0xf8, 0x53, 0x95, 0xbe,
+ 0xe3, 0x80, 0x4a, 0x10, 0xc6, 0x2a, 0xec, 0xba, 0x97, 0x20, 0x11, 0xc7,
+ 0x39, 0x99, 0x10, 0x04, 0xa0, 0xf0, 0x61, 0x7a, 0x95, 0x25, 0x8c, 0x4e,
+ 0x52, 0x75, 0xe2, 0xb6, 0xed, 0x08, 0xca, 0x14, 0xfc, 0xce, 0x22, 0x6a,
+ 0xb3, 0x4e, 0xcf, 0x46, 0x03, 0x97, 0x97, 0x03, 0x7e, 0xc0, 0xb1, 0xde,
+ 0x7b, 0xaf, 0x45, 0x33, 0xcf, 0xba, 0x3e, 0x71, 0xb7, 0xde, 0xf4, 0x25,
+ 0x25, 0xc2, 0x0d, 0x35, 0x89, 0x9d, 0x9d, 0xfb, 0x0e, 0x11, 0x79, 0x89,
+ 0x1e, 0x37, 0xc5, 0xaf, 0x8e, 0x72, 0x69, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0xa3, 0x81, 0xe7, 0x30, 0x81, 0xe4, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d,
+ 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xc0, 0x7a, 0x98, 0x68, 0x8d,
+ 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c, 0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8,
+ 0xca, 0xcc, 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
+ 0x04, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b, 0xbc, 0xf6, 0x68, 0xb5, 0x76,
+ 0xf5, 0x81, 0xb6, 0xbb, 0x62, 0x1a, 0xba, 0x5a, 0x81, 0x2f, 0x30, 0x0e,
+ 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02,
+ 0x01, 0x06, 0x30, 0x2e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x01, 0x01, 0x04, 0x22, 0x30, 0x20, 0x30, 0x1e, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x12, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x67, 0x2e, 0x73, 0x79, 0x6d, 0x63, 0x64, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
+ 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x35,
+ 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2e, 0x30, 0x2c, 0x30, 0x2a, 0xa0,
+ 0x28, 0xa0, 0x26, 0x86, 0x24, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+ 0x67, 0x2e, 0x73, 0x79, 0x6d, 0x63, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
+ 0x63, 0x72, 0x6c, 0x73, 0x2f, 0x67, 0x74, 0x67, 0x6c, 0x6f, 0x62, 0x61,
+ 0x6c, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x17, 0x06, 0x03, 0x55, 0x1d, 0x20,
+ 0x04, 0x10, 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
+ 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01,
+ 0x01, 0x00, 0x08, 0x4e, 0x04, 0xa7, 0x80, 0x7f, 0x10, 0x16, 0x43, 0x5e,
+ 0x02, 0xad, 0xd7, 0x42, 0x80, 0xf4, 0xb0, 0x8e, 0xd2, 0xae, 0xb3, 0xeb,
+ 0x11, 0x7d, 0x90, 0x84, 0x18, 0x7d, 0xe7, 0x90, 0x15, 0xfb, 0x49, 0x7f,
+ 0xa8, 0x99, 0x05, 0x91, 0xbb, 0x7a, 0xc9, 0xd6, 0x3c, 0x37, 0x18, 0x09,
+ 0x9a, 0xb6, 0xc7, 0x92, 0x20, 0x07, 0x35, 0x33, 0x09, 0xe4, 0x28, 0x63,
+ 0x72, 0x0d, 0xb4, 0xe0, 0x32, 0x9c, 0x87, 0x98, 0xc4, 0x1b, 0x76, 0x89,
+ 0x67, 0xc1, 0x50, 0x58, 0xb0, 0x13, 0xaa, 0x13, 0x1a, 0x1b, 0x32, 0xa5,
+ 0xbe, 0xea, 0x11, 0x95, 0x4c, 0x48, 0x63, 0x49, 0xe9, 0x99, 0x5d, 0x20,
+ 0x37, 0xcc, 0xfe, 0x2a, 0x69, 0x51, 0x16, 0x95, 0x4b, 0xa9, 0xde, 0x49,
+ 0x82, 0xc0, 0x10, 0x70, 0xf4, 0x2c, 0xf3, 0xec, 0xbc, 0x24, 0x24, 0xd0,
+ 0x4e, 0xac, 0xa5, 0xd9, 0x5e, 0x1e, 0x6d, 0x92, 0xc1, 0xa7, 0xac, 0x48,
+ 0x35, 0x81, 0xf9, 0xe5, 0xe4, 0x9c, 0x65, 0x69, 0xcd, 0x87, 0xa4, 0x41,
+ 0x50, 0x3f, 0x2e, 0x57, 0xa5, 0x91, 0x51, 0x12, 0x58, 0x0e, 0x8c, 0x09,
+ 0xa1, 0xac, 0x7a, 0xa4, 0x12, 0xa5, 0x27, 0xf3, 0x9a, 0x10, 0x97, 0x7d,
+ 0x55, 0x03, 0x06, 0xf7, 0x66, 0x58, 0x5f, 0x5f, 0x64, 0xe1, 0xab, 0x5d,
+ 0x6d, 0xa5, 0x39, 0x48, 0x75, 0x98, 0x4c, 0x29, 0x5a, 0x3a, 0x8d, 0xd3,
+ 0x2b, 0xca, 0x9c, 0x55, 0x04, 0xbf, 0xf4, 0xe6, 0x14, 0xd5, 0x80, 0xac,
+ 0x26, 0xed, 0x17, 0x89, 0xa6, 0x93, 0x6c, 0x5c, 0xa4, 0xcc, 0xb8, 0xf0,
+ 0x66, 0x8e, 0x64, 0xe3, 0x7d, 0x9a, 0xe2, 0x00, 0xb3, 0x49, 0xc7, 0xe4,
+ 0x0a, 0xaa, 0xdd, 0x5b, 0x83, 0xc7, 0x70, 0x90, 0x46, 0x4e, 0xbe, 0xd0,
+ 0xdb, 0x59, 0x96, 0x6c, 0x2e, 0xf5, 0x16, 0x36, 0xde, 0x71, 0xcc, 0x01,
+ 0xc2, 0x12, 0xc1, 0x21, 0xc6, 0x16, 0x00, 0x03, 0x81, 0x30, 0x82, 0x03,
+ 0x7d, 0x30, 0x82, 0x02, 0xe6, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03,
+ 0x12, 0xbb, 0xe6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x4e, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30,
+ 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, 0x45, 0x71, 0x75, 0x69,
+ 0x66, 0x61, 0x78, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 0x0b,
+ 0x13, 0x24, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53, 0x65,
+ 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
+ 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
+ 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x32, 0x30, 0x35, 0x32, 0x31,
+ 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x38, 0x30,
+ 0x38, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x42,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+ 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d,
+ 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x49, 0x6e, 0x63,
+ 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12,
+ 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f,
+ 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82,
+ 0x01, 0x01, 0x00, 0xda, 0xcc, 0x18, 0x63, 0x30, 0xfd, 0xf4, 0x17, 0x23,
+ 0x1a, 0x56, 0x7e, 0x5b, 0xdf, 0x3c, 0x6c, 0x38, 0xe4, 0x71, 0xb7, 0x78,
+ 0x91, 0xd4, 0xbc, 0xa1, 0xd8, 0x4c, 0xf8, 0xa8, 0x43, 0xb6, 0x03, 0xe9,
+ 0x4d, 0x21, 0x07, 0x08, 0x88, 0xda, 0x58, 0x2f, 0x66, 0x39, 0x29, 0xbd,
+ 0x05, 0x78, 0x8b, 0x9d, 0x38, 0xe8, 0x05, 0xb7, 0x6a, 0x7e, 0x71, 0xa4,
+ 0xe6, 0xc4, 0x60, 0xa6, 0xb0, 0xef, 0x80, 0xe4, 0x89, 0x28, 0x0f, 0x9e,
+ 0x25, 0xd6, 0xed, 0x83, 0xf3, 0xad, 0xa6, 0x91, 0xc7, 0x98, 0xc9, 0x42,
+ 0x18, 0x35, 0x14, 0x9d, 0xad, 0x98, 0x46, 0x92, 0x2e, 0x4f, 0xca, 0xf1,
+ 0x87, 0x43, 0xc1, 0x16, 0x95, 0x57, 0x2d, 0x50, 0xef, 0x89, 0x2d, 0x80,
+ 0x7a, 0x57, 0xad, 0xf2, 0xee, 0x5f, 0x6b, 0xd2, 0x00, 0x8d, 0xb9, 0x14,
+ 0xf8, 0x14, 0x15, 0x35, 0xd9, 0xc0, 0x46, 0xa3, 0x7b, 0x72, 0xc8, 0x91,
+ 0xbf, 0xc9, 0x55, 0x2b, 0xcd, 0xd0, 0x97, 0x3e, 0x9c, 0x26, 0x64, 0xcc,
+ 0xdf, 0xce, 0x83, 0x19, 0x71, 0xca, 0x4e, 0xe6, 0xd4, 0xd5, 0x7b, 0xa9,
+ 0x19, 0xcd, 0x55, 0xde, 0xc8, 0xec, 0xd2, 0x5e, 0x38, 0x53, 0xe5, 0x5c,
+ 0x4f, 0x8c, 0x2d, 0xfe, 0x50, 0x23, 0x36, 0xfc, 0x66, 0xe6, 0xcb, 0x8e,
+ 0xa4, 0x39, 0x19, 0x00, 0xb7, 0x95, 0x02, 0x39, 0x91, 0x0b, 0x0e, 0xfe,
+ 0x38, 0x2e, 0xd1, 0x1d, 0x05, 0x9a, 0xf6, 0x4d, 0x3e, 0x6f, 0x0f, 0x07,
+ 0x1d, 0xaf, 0x2c, 0x1e, 0x8f, 0x60, 0x39, 0xe2, 0xfa, 0x36, 0x53, 0x13,
+ 0x39, 0xd4, 0x5e, 0x26, 0x2b, 0xdb, 0x3d, 0xa8, 0x14, 0xbd, 0x32, 0xeb,
+ 0x18, 0x03, 0x28, 0x52, 0x04, 0x71, 0xe5, 0xab, 0x33, 0x3d, 0xe1, 0x38,
+ 0xbb, 0x07, 0x36, 0x84, 0x62, 0x9c, 0x79, 0xea, 0x16, 0x30, 0xf4, 0x5f,
+ 0xc0, 0x2b, 0xe8, 0x71, 0x6b, 0xe4, 0xf9, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0xa3, 0x81, 0xf0, 0x30, 0x81, 0xed, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d,
+ 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x48, 0xe6, 0x68, 0xf9, 0x2b,
+ 0xd2, 0xb2, 0x95, 0xd7, 0x47, 0xd8, 0x23, 0x20, 0x10, 0x4f, 0x33, 0x98,
+ 0x90, 0x9f, 0xd4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
+ 0x04, 0x14, 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64,
+ 0x0c, 0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e, 0x30, 0x0f,
+ 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03,
+ 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
+ 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x3a, 0x06, 0x03, 0x55,
+ 0x1d, 0x1f, 0x04, 0x33, 0x30, 0x31, 0x30, 0x2f, 0xa0, 0x2d, 0xa0, 0x2b,
+ 0x86, 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c,
+ 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x2f, 0x63, 0x72, 0x6c, 0x73, 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72,
+ 0x65, 0x63, 0x61, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x4e, 0x06, 0x03, 0x55,
+ 0x1d, 0x20, 0x04, 0x47, 0x30, 0x45, 0x30, 0x43, 0x06, 0x04, 0x55, 0x1d,
+ 0x20, 0x00, 0x30, 0x3b, 0x30, 0x39, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x02, 0x01, 0x16, 0x2d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a,
+ 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75,
+ 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x73, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
+ 0x6f, 0x72, 0x79, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x76, 0xe1,
+ 0x12, 0x6e, 0x4e, 0x4b, 0x16, 0x12, 0x86, 0x30, 0x06, 0xb2, 0x81, 0x08,
+ 0xcf, 0xf0, 0x08, 0xc7, 0xc7, 0x71, 0x7e, 0x66, 0xee, 0xc2, 0xed, 0xd4,
+ 0x3b, 0x1f, 0xff, 0xf0, 0xf0, 0xc8, 0x4e, 0xd6, 0x43, 0x38, 0xb0, 0xb9,
+ 0x30, 0x7d, 0x18, 0xd0, 0x55, 0x83, 0xa2, 0x6a, 0xcb, 0x36, 0x11, 0x9c,
+ 0xe8, 0x48, 0x66, 0xa3, 0x6d, 0x7f, 0xb8, 0x13, 0xd4, 0x47, 0xfe, 0x8b,
+ 0x5a, 0x5c, 0x73, 0xfc, 0xae, 0xd9, 0x1b, 0x32, 0x19, 0x38, 0xab, 0x97,
+ 0x34, 0x14, 0xaa, 0x96, 0xd2, 0xeb, 0xa3, 0x1c, 0x14, 0x08, 0x49, 0xb6,
+ 0xbb, 0xe5, 0x91, 0xef, 0x83, 0x36, 0xeb, 0x1d, 0x56, 0x6f, 0xca, 0xda,
+ 0xbc, 0x73, 0x63, 0x90, 0xe4, 0x7f, 0x7b, 0x3e, 0x22, 0xcb, 0x3d, 0x07,
+ 0xed, 0x5f, 0x38, 0x74, 0x9c, 0xe3, 0x03, 0x50, 0x4e, 0xa1, 0xaf, 0x98,
+ 0xee, 0x61, 0xf2, 0x84, 0x3f, 0x12, 0x16, 0x03, 0x03, 0x01, 0x4d, 0x0c,
+ 0x00, 0x01, 0x49, 0x03, 0x00, 0x17, 0x41, 0x04, 0x27, 0x7e, 0x6c, 0x81,
+ 0xf1, 0xb4, 0xb5, 0x60, 0x22, 0x45, 0x9b, 0x26, 0x4f, 0xb8, 0xa8, 0xbd,
+ 0xd2, 0x91, 0x88, 0x9b, 0xe0, 0xe8, 0x41, 0x4d, 0x7c, 0xab, 0xcf, 0xf7,
+ 0x3f, 0x8f, 0x23, 0xd1, 0x18, 0xdd, 0xb7, 0x27, 0xbd, 0xcf, 0xd3, 0x14,
+ 0x71, 0xca, 0xf9, 0x7e, 0xb8, 0xe8, 0x15, 0x59, 0xa2, 0x97, 0x66, 0x27,
+ 0x45, 0xc3, 0x40, 0xf7, 0xa8, 0x77, 0x61, 0x05, 0x9b, 0xb2, 0xa9, 0xd0,
+ 0x06, 0x01, 0x01, 0x00, 0x6e, 0xd0, 0x13, 0x15, 0x52, 0x29, 0xdb, 0x2c,
+ 0x60, 0x3c, 0x2d, 0xf3, 0x6f, 0xc5, 0xac, 0x44, 0x53, 0x47, 0x3b, 0x17,
+ 0xbc, 0xaf, 0xaa, 0x9f, 0x5d, 0xf5, 0x2e, 0x7a, 0x9c, 0x32, 0x58, 0xb5,
+ 0x37, 0x1a, 0xce, 0x4c, 0x12, 0x9e, 0x47, 0xf0, 0xfd, 0x85, 0x38, 0x39,
+ 0xc1, 0xec, 0xd8, 0x06, 0xc8, 0x84, 0x87, 0x03, 0xfa, 0x41, 0xf9, 0x88,
+ 0xa0, 0xef, 0x84, 0x87, 0x76, 0x6e, 0x61, 0xfc, 0x1c, 0x78, 0xd8, 0x70,
+ 0xa8, 0x65, 0x3a, 0x1e, 0x84, 0xac, 0x14, 0x78, 0x74, 0x18, 0x7f, 0xdd,
+ 0x35, 0x2e, 0x99, 0xd8, 0x3d, 0x68, 0x66, 0x16, 0x7a, 0x83, 0x16, 0xa6,
+ 0x21, 0x18, 0x71, 0x6f, 0x58, 0x32, 0x60, 0xa3, 0x70, 0xa6, 0xca, 0x04,
+ 0xd5, 0x09, 0xbe, 0xc3, 0x32, 0xc9, 0xee, 0x5d, 0x9a, 0x56, 0xdb, 0xf6,
+ 0x17, 0xf1, 0x2c, 0x6d, 0x71, 0x4f, 0xf7, 0x8a, 0x2a, 0xa3, 0xcf, 0xb9,
+ 0x86, 0x0a, 0xc2, 0xfd, 0x75, 0xab, 0xb2, 0x75, 0x39, 0xb5, 0xf5, 0x2b,
+ 0xb2, 0x80, 0x9e, 0x9b, 0x32, 0x26, 0x25, 0x6c, 0x0e, 0x71, 0xdf, 0xc0,
+ 0x42, 0x4e, 0x74, 0xd8, 0xb0, 0x9b, 0xa5, 0x15, 0xe5, 0x96, 0xd7, 0x30,
+ 0xdf, 0x33, 0x3d, 0xfd, 0xba, 0xf7, 0x59, 0x7d, 0xdb, 0xc9, 0x31, 0x3d,
+ 0x70, 0xe4, 0xd4, 0x91, 0x97, 0x70, 0x2d, 0xf2, 0x48, 0xcd, 0x84, 0x2d,
+ 0x70, 0x48, 0xbc, 0xd6, 0x6b, 0xaf, 0xdd, 0xf6, 0x7d, 0xad, 0xb9, 0x89,
+ 0x94, 0x7c, 0x59, 0x0c, 0x3f, 0x3e, 0xe2, 0x8d, 0x4c, 0x81, 0x4a, 0x15,
+ 0x09, 0xb9, 0xde, 0xc1, 0xe6, 0xe6, 0x5d, 0x28, 0x2d, 0x1d, 0xb8, 0x45,
+ 0x17, 0x42, 0x55, 0xe3, 0x2a, 0xcf, 0x55, 0x26, 0x66, 0x79, 0xf1, 0xbb,
+ 0x2a, 0x25, 0x28, 0x78, 0xa1, 0x63, 0x90, 0xec, 0xec, 0xa7, 0xee, 0x61,
+ 0x1c, 0xac, 0x19, 0x45, 0xdd, 0x82, 0xae, 0x52, 0x16, 0x03, 0x03, 0x00,
+ 0x04, 0x0e, 0x00, 0x00, 0x00
+ ];
+
+ #[bench]
+ fn bench_tls_record_serverhello(b: &mut Bencher) {
+ let bytes = &SERVER_REPLY1[0..64];
+ b.iter(|| {
+ let _ = parse_tls_plaintext(&bytes);
+ })
+ }
+
+ #[bench]
+ fn bench_tls_record_certificate(b: &mut Bencher) {
+ let bytes = &SERVER_REPLY1[64..3150];
+ b.iter(|| {
+ let _ = parse_tls_plaintext(&bytes);
+ })
+ }
+
+ #[bench]
+ fn bench_tls_record_serverkeyexchange(b: &mut Bencher) {
+ let bytes = &SERVER_REPLY1[3150..3488];
+ b.iter(|| {
+ let _ = parse_tls_plaintext(&bytes);
+ })
+ }
+
+ #[bench]
+ fn bench_tls_record_serverdone(b: &mut Bencher) {
+ let bytes = &SERVER_REPLY1[3488..];
+ b.iter(|| {
+ let _ = parse_tls_plaintext(&bytes);
+ })
+ }
+} // mod tls_handshake
diff --git a/rust/vendor/tls-parser/build.rs b/rust/vendor/tls-parser/build.rs
new file mode 100644
index 0000000..e626fcf
--- /dev/null
+++ b/rust/vendor/tls-parser/build.rs
@@ -0,0 +1,91 @@
+extern crate phf_codegen;
+
+use std::env;
+use std::fs::File;
+use std::io::BufRead;
+use std::io::{BufReader, BufWriter, Write};
+use std::path::Path;
+
+fn titlecase_word(word: &str) -> String {
+ word.chars()
+ .enumerate()
+ .map(|(i, c)| {
+ if i == 0 {
+ c.to_uppercase().collect::<String>()
+ } else {
+ c.to_lowercase().collect::<String>()
+ }
+ })
+ .collect()
+}
+
+fn main() {
+ let path_txt =
+ Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join("scripts/tls-ciphersuites.txt");
+ let display = path_txt.display();
+ let file = match File::open(&path_txt) {
+ // The `description` method of `io::Error` returns a string that
+ // describes the error
+ Err(why) => panic!("couldn't open {}: {}", display, why),
+ Ok(file) => file,
+ };
+ let f = BufReader::new(file);
+
+ let path = Path::new(&env::var("OUT_DIR").unwrap()).join("codegen.rs");
+ let mut file = BufWriter::new(File::create(&path).unwrap());
+
+ let mut map = phf_codegen::Map::new();
+ for line in f.lines() {
+ let l = line.unwrap();
+ let mut v: Vec<&str> = l.split(':').collect();
+
+ if v[5].is_empty() {
+ v[5] = "NULL"
+ }
+
+ let au = match v[3] {
+ "SRP+DSS" => String::from("Srp_Dss"),
+ "SRP+RSA" => String::from("Srp_Rsa"),
+ _ => titlecase_word(v[3]).replace("+", "_"),
+ };
+
+ let enc = match v[4] {
+ "3DES" => String::from("TripleDes"),
+ "CHACHA20_POLY1305" => String::from("Chacha20_Poly1305"),
+ _ => titlecase_word(v[4]),
+ };
+
+ let mac = String::from(match v[7] {
+ "NULL" => "Null",
+ "HMAC-MD5" => "HmacMd5",
+ "HMAC-SHA1" => "HmacSha1",
+ "HMAC-SHA256" => "HmacSha256",
+ "HMAC-SHA384" => "HmacSha384",
+ "AEAD" => "Aead",
+ _ => panic!("Unknown mac {}", v[7]),
+ });
+
+ let key = u16::from_str_radix(v[0], 16).unwrap();
+ let val =
+ format!(
+ "TlsCipherSuite{{ name:\"{}\", id:0x{}, kx:TlsCipherKx::{}, au:TlsCipherAu::{}, enc:TlsCipherEnc::{}, enc_mode:TlsCipherEncMode::{}, enc_size:{}, mac:TlsCipherMac::{}, mac_size:{},}}",
+ v[1],v[0],
+ titlecase_word(v[2]), // kx
+ au, // au
+ enc, // enc
+ titlecase_word(v[5]), // enc_mode
+ v[6], // enc_size
+ mac, // mac
+ v[8], // mac_size
+ ).clone();
+
+ map.entry(key, val.as_str());
+ }
+
+ writeln!(
+ &mut file,
+ "pub static CIPHERS: phf::Map<u16, TlsCipherSuite> = {};",
+ map.build()
+ )
+ .unwrap();
+}
diff --git a/rust/vendor/tls-parser/scripts/extract-iana-ciphers.py b/rust/vendor/tls-parser/scripts/extract-iana-ciphers.py
new file mode 100755
index 0000000..7a2b498
--- /dev/null
+++ b/rust/vendor/tls-parser/scripts/extract-iana-ciphers.py
@@ -0,0 +1,180 @@
+#!/usr/bin/python
+
+import urllib2
+from BeautifulSoup import BeautifulSoup, ResultSet
+file = urllib2.urlopen('http://www.iana.org/assignments/tls-parameters/tls-parameters.xml')
+data = file.read()
+with open('tls-parameters.xml', 'wb') as myFile:
+ myFile.write(data)
+file.close()
+
+dom = BeautifulSoup(data)
+
+#ciphersuites=dom.findAll ("registry")[4]
+ciphersuites=dom.findAll (id="tls-parameters-4")
+if isinstance(ciphersuites,ResultSet):
+ ciphersuites = ciphersuites.pop()
+
+for i in ciphersuites.findAll ("record"):
+ value = "".join(i.value.contents)
+ desc = "".join (i.description.contents)
+
+ ignore_keywords = [
+ "Unassigned",
+ "Reserved",
+ ]
+ f = filter(desc.startswith,ignore_keywords)
+
+ if len(f) > 0:
+ continue
+
+ if desc == "TLS_EMPTY_RENEGOTIATION_INFO_SCSV":
+ continue
+ elif desc == "TLS_FALLBACK_SCSV":
+ continue
+
+ rfc = "NONE"
+ if i.xref:
+ rfc_tmp = filter (lambda (var,val) : var == "data", i.xref.attrs)
+ if len (rfc_tmp) > 0:
+ # rfc = rfc_tmp[0][1][3:7]
+ rfc = rfc_tmp[0][1]
+
+ real_value = "".join (map (lambda x : "%2.2x" % (int (x, 16)), value.split (",")))
+
+ minver = 0x0300
+ maxver = 0xffff
+
+ if rfc == "rfc8446":
+ kxau = ["TLS13"]
+ encmac = desc[4:] # skip "TLS_"
+ elif rfc == "draft-camwinget-tls-ts13-macciphersuites":
+ kxau = ["TLS13"]
+ encmac = "NULL_" + desc.split("_")[1] # forge string like NULL_SHA256
+ else:
+ (_kxau, encmac) = desc.split("_WITH_")
+ kxau = _kxau.split ("_")[1:]
+ export = 0
+ if kxau[-1] == "EXPORT":
+ export = 1
+ maxver = 0x302
+ kxau = kxau[:-1]
+ if len (kxau) == 1:
+ kx = kxau[0]
+ au = kxau[0]
+ elif kxau[0] == "SRP":
+ kx = "_".join (kxau[0:1])
+ au = kx
+ if len (kxau) > 2:
+ au += "+" + "_".join (kxau[2:])
+ elif kxau[0] == "GOSTR341112":
+ # unsupported suites from https://datatracker.ietf.org/doc/draft-smyshlyaev-tls12-gost-suites/
+ continue
+ else:
+ kx, au = kxau
+ if au == "anon":
+ au = "NULL"
+
+ _encmac = encmac.split ("_")
+ hashfun = _encmac [-1]
+ _encstr = "_".join (_encmac [:-1])
+ _enc = _encmac [:-1]
+
+ if _encstr == "DES40_CBC":
+ enc = "DES"
+ encmode = "CBC"
+ encsize = 40
+ elif len (_enc) == 3 and _enc[1] == "CBC" and _enc[2] == "40":
+ enc = _enc[0]
+ encmode = "CBC"
+ encsize = 40
+ elif _encstr == "DES_CBC":
+ enc = "DES"
+ encmode = "CBC"
+ encsize = 56
+ elif _encstr == "IDEA_CBC":
+ enc = "IDEA"
+ encmode = "CBC"
+ encsize = 128
+ elif _encstr == "3DES_EDE_CBC":
+ enc = "3DES"
+ encmode = "CBC"
+ encsize = 168
+ elif _encstr == "NULL":
+ enc = "NULL"
+ encmode = ""
+ encsize = 0
+ elif _encstr == "SEED_CBC":
+ enc = "SEED"
+ encmode = "CBC"
+ encsize = 128
+ elif _encstr == "CHACHA20_POLY1305":
+ enc = "CHACHA20_POLY1305"
+ encmode = "CBC"
+ encsize = 256
+ elif len (_enc) == 2:
+ enc = _enc[0]
+ encmode = ""
+ encsize = int (_enc[1])
+ else:
+ enc = _enc[0]
+ encmode = _enc[2]
+ encsize = int (_enc[1])
+
+ prf = "DEFAULT"
+ prfsize = 0
+
+ # fix crap from recent changes
+ if hashfun == "8":
+ hashfun = "_".join([encmode,hashfun])
+ encmode = ""
+
+ if hashfun == "NULL":
+ mac = "NULL"
+ macsize = 0
+ elif hashfun == "MD5":
+ mac = "HMAC-MD5"
+ macsize = 128
+ elif hashfun == "SHA":
+ mac = "HMAC-SHA1"
+ macsize = 160
+ elif hashfun == "SHA256":
+ mac = "HMAC-SHA256"
+ macsize = 256
+ prf = "SHA256"
+ prfsize = 256
+ minver = 0x303
+ elif hashfun == "SHA384":
+ mac = "HMAC-SHA384"
+ macsize = 384
+ prf = "SHA384"
+ prfsize = 384
+ minver = 0x303
+ elif hashfun == "CCM":
+ #print encmode
+ #mac = "CCM"
+ #macsize = 0
+ minver = 0x303
+ encmode = "CCM"
+ elif hashfun == "CCM_8":
+ #print encmode
+ #mac = "CCM_8"
+ #macsize = 0
+ minver = 0x303
+ encmode = "CCM"
+ else:
+ print desc
+ print encmac
+ print hashfun
+ raise "Unsupported."
+
+ if encmode == "GCM" or encmode == "CCM":
+ mac = "AEAD"
+ macsize = encsize
+ minver = 0x303
+ if _encstr == "CHACHA20_POLY1305":
+ mac = "AEAD"
+ macsize = encsize
+ minver = 0x303
+
+ print "%s:%s:%s:%s:%s:%s:%d:%s:%d:%s:%d:%s:%d:%4.4x:%4.4x" % (real_value, desc, kx, au, enc, encmode, encsize, mac, macsize, prf, prfsize, rfc, export, minver, maxver)
diff --git a/rust/vendor/tls-parser/scripts/tls-ciphersuites.txt b/rust/vendor/tls-parser/scripts/tls-ciphersuites.txt
new file mode 100644
index 0000000..f34fca9
--- /dev/null
+++ b/rust/vendor/tls-parser/scripts/tls-ciphersuites.txt
@@ -0,0 +1,343 @@
+0000:TLS_NULL_WITH_NULL_NULL:NULL:NULL:NULL::0:NULL:0:DEFAULT:0:rfc5246:0:0300:ffff
+0001:TLS_RSA_WITH_NULL_MD5:RSA:RSA:NULL::0:HMAC-MD5:128:DEFAULT:0:rfc5246:0:0300:ffff
+0002:TLS_RSA_WITH_NULL_SHA:RSA:RSA:NULL::0:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+0003:TLS_RSA_EXPORT_WITH_RC4_40_MD5:RSA:RSA:RC4::40:HMAC-MD5:128:DEFAULT:0:rfc4346,rfc6347:1:0300:ffff
+0004:TLS_RSA_WITH_RC4_128_MD5:RSA:RSA:RC4::128:HMAC-MD5:128:DEFAULT:0:rfc5246,rfc6347:0:0300:ffff
+0005:TLS_RSA_WITH_RC4_128_SHA:RSA:RSA:RC4::128:HMAC-SHA1:160:DEFAULT:0:rfc5246,rfc6347:0:0300:ffff
+0006:TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5:RSA:RSA:RC2:CBC:40:HMAC-MD5:128:DEFAULT:0:rfc4346:1:0300:ffff
+0007:TLS_RSA_WITH_IDEA_CBC_SHA:RSA:RSA:IDEA:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5469,sc-tls-des-idea-ciphers-to-historic:0:0300:ffff
+0008:TLS_RSA_EXPORT_WITH_DES40_CBC_SHA:RSA:RSA:DES:CBC:40:HMAC-SHA1:160:DEFAULT:0:rfc4346:1:0300:ffff
+0009:TLS_RSA_WITH_DES_CBC_SHA:RSA:RSA:DES:CBC:56:HMAC-SHA1:160:DEFAULT:0:rfc5469,sc-tls-des-idea-ciphers-to-historic:0:0300:ffff
+000a:TLS_RSA_WITH_3DES_EDE_CBC_SHA:RSA:RSA:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+000b:TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:DH:DSS:DES:CBC:40:HMAC-SHA1:160:DEFAULT:0:rfc4346:1:0300:ffff
+000c:TLS_DH_DSS_WITH_DES_CBC_SHA:DH:DSS:DES:CBC:56:HMAC-SHA1:160:DEFAULT:0:rfc5469,sc-tls-des-idea-ciphers-to-historic:0:0300:ffff
+000d:TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:DH:DSS:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+000e:TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:DH:RSA:DES:CBC:40:HMAC-SHA1:160:DEFAULT:0:rfc4346:1:0300:ffff
+000f:TLS_DH_RSA_WITH_DES_CBC_SHA:DH:RSA:DES:CBC:56:HMAC-SHA1:160:DEFAULT:0:rfc5469,sc-tls-des-idea-ciphers-to-historic:0:0300:ffff
+0010:TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:DH:RSA:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+0011:TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:DHE:DSS:DES:CBC:40:HMAC-SHA1:160:DEFAULT:0:rfc4346:1:0300:ffff
+0012:TLS_DHE_DSS_WITH_DES_CBC_SHA:DHE:DSS:DES:CBC:56:HMAC-SHA1:160:DEFAULT:0:rfc5469,sc-tls-des-idea-ciphers-to-historic:0:0300:ffff
+0013:TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:DHE:DSS:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+0014:TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:DHE:RSA:DES:CBC:40:HMAC-SHA1:160:DEFAULT:0:rfc4346:1:0300:ffff
+0015:TLS_DHE_RSA_WITH_DES_CBC_SHA:DHE:RSA:DES:CBC:56:HMAC-SHA1:160:DEFAULT:0:rfc5469,sc-tls-des-idea-ciphers-to-historic:0:0300:ffff
+0016:TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:DHE:RSA:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+0017:TLS_DH_anon_EXPORT_WITH_RC4_40_MD5:DH:NULL:RC4::40:HMAC-MD5:128:DEFAULT:0:rfc4346,rfc6347:1:0300:ffff
+0018:TLS_DH_anon_WITH_RC4_128_MD5:DH:NULL:RC4::128:HMAC-MD5:128:DEFAULT:0:rfc5246,rfc6347:0:0300:ffff
+0019:TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA:DH:NULL:DES:CBC:40:HMAC-SHA1:160:DEFAULT:0:rfc4346:1:0300:ffff
+001a:TLS_DH_anon_WITH_DES_CBC_SHA:DH:NULL:DES:CBC:56:HMAC-SHA1:160:DEFAULT:0:rfc5469,sc-tls-des-idea-ciphers-to-historic:0:0300:ffff
+001b:TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:DH:NULL:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+001e:TLS_KRB5_WITH_DES_CBC_SHA:KRB5:KRB5:DES:CBC:56:HMAC-SHA1:160:DEFAULT:0:rfc2712:0:0300:ffff
+001f:TLS_KRB5_WITH_3DES_EDE_CBC_SHA:KRB5:KRB5:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc2712:0:0300:ffff
+0020:TLS_KRB5_WITH_RC4_128_SHA:KRB5:KRB5:RC4::128:HMAC-SHA1:160:DEFAULT:0:rfc2712,rfc6347:0:0300:ffff
+0021:TLS_KRB5_WITH_IDEA_CBC_SHA:KRB5:KRB5:IDEA:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc2712:0:0300:ffff
+0022:TLS_KRB5_WITH_DES_CBC_MD5:KRB5:KRB5:DES:CBC:56:HMAC-MD5:128:DEFAULT:0:rfc2712:0:0300:ffff
+0023:TLS_KRB5_WITH_3DES_EDE_CBC_MD5:KRB5:KRB5:3DES:CBC:168:HMAC-MD5:128:DEFAULT:0:rfc2712:0:0300:ffff
+0024:TLS_KRB5_WITH_RC4_128_MD5:KRB5:KRB5:RC4::128:HMAC-MD5:128:DEFAULT:0:rfc2712,rfc6347:0:0300:ffff
+0025:TLS_KRB5_WITH_IDEA_CBC_MD5:KRB5:KRB5:IDEA:CBC:128:HMAC-MD5:128:DEFAULT:0:rfc2712:0:0300:ffff
+0026:TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA:KRB5:KRB5:DES:CBC:40:HMAC-SHA1:160:DEFAULT:0:rfc2712:1:0300:ffff
+0027:TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA:KRB5:KRB5:RC2:CBC:40:HMAC-SHA1:160:DEFAULT:0:rfc2712:1:0300:ffff
+0028:TLS_KRB5_EXPORT_WITH_RC4_40_SHA:KRB5:KRB5:RC4::40:HMAC-SHA1:160:DEFAULT:0:rfc2712,rfc6347:1:0300:ffff
+0029:TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5:KRB5:KRB5:DES:CBC:40:HMAC-MD5:128:DEFAULT:0:rfc2712:1:0300:ffff
+002a:TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5:KRB5:KRB5:RC2:CBC:40:HMAC-MD5:128:DEFAULT:0:rfc2712:1:0300:ffff
+002b:TLS_KRB5_EXPORT_WITH_RC4_40_MD5:KRB5:KRB5:RC4::40:HMAC-MD5:128:DEFAULT:0:rfc2712,rfc6347:1:0300:ffff
+002c:TLS_PSK_WITH_NULL_SHA:PSK:PSK:NULL::0:HMAC-SHA1:160:DEFAULT:0:rfc4785:0:0300:ffff
+002d:TLS_DHE_PSK_WITH_NULL_SHA:DHE:PSK:NULL::0:HMAC-SHA1:160:DEFAULT:0:rfc4785:0:0300:ffff
+002e:TLS_RSA_PSK_WITH_NULL_SHA:RSA:PSK:NULL::0:HMAC-SHA1:160:DEFAULT:0:rfc4785:0:0300:ffff
+002f:TLS_RSA_WITH_AES_128_CBC_SHA:RSA:RSA:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+0030:TLS_DH_DSS_WITH_AES_128_CBC_SHA:DH:DSS:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+0031:TLS_DH_RSA_WITH_AES_128_CBC_SHA:DH:RSA:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+0032:TLS_DHE_DSS_WITH_AES_128_CBC_SHA:DHE:DSS:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+0033:TLS_DHE_RSA_WITH_AES_128_CBC_SHA:DHE:RSA:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+0034:TLS_DH_anon_WITH_AES_128_CBC_SHA:DH:NULL:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+0035:TLS_RSA_WITH_AES_256_CBC_SHA:RSA:RSA:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+0036:TLS_DH_DSS_WITH_AES_256_CBC_SHA:DH:DSS:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+0037:TLS_DH_RSA_WITH_AES_256_CBC_SHA:DH:RSA:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+0038:TLS_DHE_DSS_WITH_AES_256_CBC_SHA:DHE:DSS:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+0039:TLS_DHE_RSA_WITH_AES_256_CBC_SHA:DHE:RSA:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+003a:TLS_DH_anon_WITH_AES_256_CBC_SHA:DH:NULL:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5246:0:0300:ffff
+003b:TLS_RSA_WITH_NULL_SHA256:RSA:RSA:NULL::0:HMAC-SHA256:256:SHA256:256:rfc5246:0:0300:ffff
+003c:TLS_RSA_WITH_AES_128_CBC_SHA256:RSA:RSA:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5246:0:0300:ffff
+003d:TLS_RSA_WITH_AES_256_CBC_SHA256:RSA:RSA:AES:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5246:0:0300:ffff
+003e:TLS_DH_DSS_WITH_AES_128_CBC_SHA256:DH:DSS:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5246:0:0300:ffff
+003f:TLS_DH_RSA_WITH_AES_128_CBC_SHA256:DH:RSA:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5246:0:0300:ffff
+0040:TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:DHE:DSS:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5246:0:0300:ffff
+0041:TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:RSA:RSA:CAMELLIA:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5932:0:0300:ffff
+0042:TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:DH:DSS:CAMELLIA:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5932:0:0300:ffff
+0043:TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:DH:RSA:CAMELLIA:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5932:0:0300:ffff
+0044:TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:DHE:DSS:CAMELLIA:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5932:0:0300:ffff
+0045:TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:DHE:RSA:CAMELLIA:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5932:0:0300:ffff
+0046:TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA:DH:NULL:CAMELLIA:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5932:0:0300:ffff
+0067:TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:DHE:RSA:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5246:0:0300:ffff
+0068:TLS_DH_DSS_WITH_AES_256_CBC_SHA256:DH:DSS:AES:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5246:0:0300:ffff
+0069:TLS_DH_RSA_WITH_AES_256_CBC_SHA256:DH:RSA:AES:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5246:0:0300:ffff
+006a:TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:DHE:DSS:AES:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5246:0:0300:ffff
+006b:TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:DHE:RSA:AES:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5246:0:0300:ffff
+006c:TLS_DH_anon_WITH_AES_128_CBC_SHA256:DH:NULL:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5246:0:0300:ffff
+006d:TLS_DH_anon_WITH_AES_256_CBC_SHA256:DH:NULL:AES:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5246:0:0300:ffff
+0084:TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:RSA:RSA:CAMELLIA:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5932:0:0300:ffff
+0085:TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:DH:DSS:CAMELLIA:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5932:0:0300:ffff
+0086:TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:DH:RSA:CAMELLIA:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5932:0:0300:ffff
+0087:TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:DHE:DSS:CAMELLIA:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5932:0:0300:ffff
+0088:TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:DHE:RSA:CAMELLIA:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5932:0:0300:ffff
+0089:TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA:DH:NULL:CAMELLIA:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5932:0:0300:ffff
+008a:TLS_PSK_WITH_RC4_128_SHA:PSK:PSK:RC4::128:HMAC-SHA1:160:DEFAULT:0:rfc4279,rfc6347:0:0300:ffff
+008b:TLS_PSK_WITH_3DES_EDE_CBC_SHA:PSK:PSK:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc4279:0:0300:ffff
+008c:TLS_PSK_WITH_AES_128_CBC_SHA:PSK:PSK:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc4279:0:0300:ffff
+008d:TLS_PSK_WITH_AES_256_CBC_SHA:PSK:PSK:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc4279:0:0300:ffff
+008e:TLS_DHE_PSK_WITH_RC4_128_SHA:DHE:PSK:RC4::128:HMAC-SHA1:160:DEFAULT:0:rfc4279,rfc6347:0:0300:ffff
+008f:TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:DHE:PSK:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc4279:0:0300:ffff
+0090:TLS_DHE_PSK_WITH_AES_128_CBC_SHA:DHE:PSK:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc4279:0:0300:ffff
+0091:TLS_DHE_PSK_WITH_AES_256_CBC_SHA:DHE:PSK:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc4279:0:0300:ffff
+0092:TLS_RSA_PSK_WITH_RC4_128_SHA:RSA:PSK:RC4::128:HMAC-SHA1:160:DEFAULT:0:rfc4279,rfc6347:0:0300:ffff
+0093:TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:RSA:PSK:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc4279:0:0300:ffff
+0094:TLS_RSA_PSK_WITH_AES_128_CBC_SHA:RSA:PSK:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc4279:0:0300:ffff
+0095:TLS_RSA_PSK_WITH_AES_256_CBC_SHA:RSA:PSK:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc4279:0:0300:ffff
+0096:TLS_RSA_WITH_SEED_CBC_SHA:RSA:RSA:SEED:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc4162:0:0300:ffff
+0097:TLS_DH_DSS_WITH_SEED_CBC_SHA:DH:DSS:SEED:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc4162:0:0300:ffff
+0098:TLS_DH_RSA_WITH_SEED_CBC_SHA:DH:RSA:SEED:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc4162:0:0300:ffff
+0099:TLS_DHE_DSS_WITH_SEED_CBC_SHA:DHE:DSS:SEED:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc4162:0:0300:ffff
+009a:TLS_DHE_RSA_WITH_SEED_CBC_SHA:DHE:RSA:SEED:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc4162:0:0300:ffff
+009b:TLS_DH_anon_WITH_SEED_CBC_SHA:DH:NULL:SEED:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc4162:0:0300:ffff
+009c:TLS_RSA_WITH_AES_128_GCM_SHA256:RSA:RSA:AES:GCM:128:AEAD:128:SHA256:256:rfc5288:0:0300:ffff
+009d:TLS_RSA_WITH_AES_256_GCM_SHA384:RSA:RSA:AES:GCM:256:AEAD:256:SHA384:384:rfc5288:0:0300:ffff
+009e:TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:DHE:RSA:AES:GCM:128:AEAD:128:SHA256:256:rfc5288:0:0300:ffff
+009f:TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:DHE:RSA:AES:GCM:256:AEAD:256:SHA384:384:rfc5288:0:0300:ffff
+00a0:TLS_DH_RSA_WITH_AES_128_GCM_SHA256:DH:RSA:AES:GCM:128:AEAD:128:SHA256:256:rfc5288:0:0300:ffff
+00a1:TLS_DH_RSA_WITH_AES_256_GCM_SHA384:DH:RSA:AES:GCM:256:AEAD:256:SHA384:384:rfc5288:0:0300:ffff
+00a2:TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:DHE:DSS:AES:GCM:128:AEAD:128:SHA256:256:rfc5288:0:0300:ffff
+00a3:TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:DHE:DSS:AES:GCM:256:AEAD:256:SHA384:384:rfc5288:0:0300:ffff
+00a4:TLS_DH_DSS_WITH_AES_128_GCM_SHA256:DH:DSS:AES:GCM:128:AEAD:128:SHA256:256:rfc5288:0:0300:ffff
+00a5:TLS_DH_DSS_WITH_AES_256_GCM_SHA384:DH:DSS:AES:GCM:256:AEAD:256:SHA384:384:rfc5288:0:0300:ffff
+00a6:TLS_DH_anon_WITH_AES_128_GCM_SHA256:DH:NULL:AES:GCM:128:AEAD:128:SHA256:256:rfc5288:0:0300:ffff
+00a7:TLS_DH_anon_WITH_AES_256_GCM_SHA384:DH:NULL:AES:GCM:256:AEAD:256:SHA384:384:rfc5288:0:0300:ffff
+00a8:TLS_PSK_WITH_AES_128_GCM_SHA256:PSK:PSK:AES:GCM:128:AEAD:128:SHA256:256:rfc5487:0:0300:ffff
+00a9:TLS_PSK_WITH_AES_256_GCM_SHA384:PSK:PSK:AES:GCM:256:AEAD:256:SHA384:384:rfc5487:0:0300:ffff
+00aa:TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:DHE:PSK:AES:GCM:128:AEAD:128:SHA256:256:rfc5487:0:0300:ffff
+00ab:TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:DHE:PSK:AES:GCM:256:AEAD:256:SHA384:384:rfc5487:0:0300:ffff
+00ac:TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:RSA:PSK:AES:GCM:128:AEAD:128:SHA256:256:rfc5487:0:0300:ffff
+00ad:TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:RSA:PSK:AES:GCM:256:AEAD:256:SHA384:384:rfc5487:0:0300:ffff
+00ae:TLS_PSK_WITH_AES_128_CBC_SHA256:PSK:PSK:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5487:0:0300:ffff
+00af:TLS_PSK_WITH_AES_256_CBC_SHA384:PSK:PSK:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5487:0:0300:ffff
+00b0:TLS_PSK_WITH_NULL_SHA256:PSK:PSK:NULL::0:HMAC-SHA256:256:SHA256:256:rfc5487:0:0300:ffff
+00b1:TLS_PSK_WITH_NULL_SHA384:PSK:PSK:NULL::0:HMAC-SHA384:384:SHA384:384:rfc5487:0:0300:ffff
+00b2:TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:DHE:PSK:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5487:0:0300:ffff
+00b3:TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:DHE:PSK:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5487:0:0300:ffff
+00b4:TLS_DHE_PSK_WITH_NULL_SHA256:DHE:PSK:NULL::0:HMAC-SHA256:256:SHA256:256:rfc5487:0:0300:ffff
+00b5:TLS_DHE_PSK_WITH_NULL_SHA384:DHE:PSK:NULL::0:HMAC-SHA384:384:SHA384:384:rfc5487:0:0300:ffff
+00b6:TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:RSA:PSK:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5487:0:0300:ffff
+00b7:TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:RSA:PSK:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5487:0:0300:ffff
+00b8:TLS_RSA_PSK_WITH_NULL_SHA256:RSA:PSK:NULL::0:HMAC-SHA256:256:SHA256:256:rfc5487:0:0300:ffff
+00b9:TLS_RSA_PSK_WITH_NULL_SHA384:RSA:PSK:NULL::0:HMAC-SHA384:384:SHA384:384:rfc5487:0:0300:ffff
+00ba:TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:RSA:RSA:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5932:0:0300:ffff
+00bb:TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:DH:DSS:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5932:0:0300:ffff
+00bc:TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:DH:RSA:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5932:0:0300:ffff
+00bd:TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:DHE:DSS:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5932:0:0300:ffff
+00be:TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:DHE:RSA:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5932:0:0300:ffff
+00bf:TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256:DH:NULL:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5932:0:0300:ffff
+00c0:TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:RSA:RSA:CAMELLIA:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5932:0:0300:ffff
+00c1:TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:DH:DSS:CAMELLIA:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5932:0:0300:ffff
+00c2:TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:DH:RSA:CAMELLIA:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5932:0:0300:ffff
+00c3:TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:DHE:DSS:CAMELLIA:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5932:0:0300:ffff
+00c4:TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:DHE:RSA:CAMELLIA:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5932:0:0300:ffff
+00c5:TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256:DH:NULL:CAMELLIA:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5932:0:0300:ffff
+00c6:TLS_SM4_GCM_SM3:TLS13:TLS13:SM4:GCM:128:AEAD:128:SM3:256:rfc8998:0:0300:ffff
+00c7:TLS_SM4_CCM_SM3:TLS13:TLS13:SM4:CCM:128:AEAD:128:SM3:256:rfc8998:0:0300:ffff
+00ff:TLS_EMPTY_RENEGOTIATION_INFO_SCSV:NULL:NULL:NULL::0:NULL:0:NULL:0:[RFC5746]:0:0:0
+1301:TLS_AES_128_GCM_SHA256:TLS13:TLS13:AES:GCM:128:AEAD:128:SHA256:256:rfc8446:0:0300:ffff
+1302:TLS_AES_256_GCM_SHA384:TLS13:TLS13:AES:GCM:256:AEAD:256:SHA384:384:rfc8446:0:0300:ffff
+1303:TLS_CHACHA20_POLY1305_SHA256:TLS13:TLS13:CHACHA20_POLY1305::128:AEAD:128:SHA256:256:rfc8446:0:0300:ffff
+1304:TLS_AES_128_CCM_SHA256:TLS13:TLS13:AES:CCM:128:AEAD:128:SHA256:256:rfc8446:0:0300:ffff
+1305:TLS_AES_128_CCM_8_SHA256:TLS13:TLS13:AES:CCM:128:AEAD:128:SHA256:256:rfc8446,iesg action 2018-08-16:0:0300:ffff
+5600:TLS_FALLBACK_SCSV:NULL:NULL:NULL::0:NULL:0:NULL:0:[RFC7507]:0:0:0
+c001:TLS_ECDH_ECDSA_WITH_NULL_SHA:ECDH:ECDSA:NULL::0:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c002:TLS_ECDH_ECDSA_WITH_RC4_128_SHA:ECDH:ECDSA:RC4::128:HMAC-SHA1:160:DEFAULT:0:rfc8422,rfc6347:0:0300:ffff
+c003:TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:ECDH:ECDSA:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c004:TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:ECDH:ECDSA:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c005:TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:ECDH:ECDSA:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c006:TLS_ECDHE_ECDSA_WITH_NULL_SHA:ECDHE:ECDSA:NULL::0:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c007:TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:ECDHE:ECDSA:RC4::128:HMAC-SHA1:160:DEFAULT:0:rfc8422,rfc6347:0:0300:ffff
+c008:TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:ECDHE:ECDSA:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c009:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:ECDHE:ECDSA:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c00a:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:ECDHE:ECDSA:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c00b:TLS_ECDH_RSA_WITH_NULL_SHA:ECDH:RSA:NULL::0:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c00c:TLS_ECDH_RSA_WITH_RC4_128_SHA:ECDH:RSA:RC4::128:HMAC-SHA1:160:DEFAULT:0:rfc8422,rfc6347:0:0300:ffff
+c00d:TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:ECDH:RSA:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c00e:TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:ECDH:RSA:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c00f:TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:ECDH:RSA:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c010:TLS_ECDHE_RSA_WITH_NULL_SHA:ECDHE:RSA:NULL::0:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c011:TLS_ECDHE_RSA_WITH_RC4_128_SHA:ECDHE:RSA:RC4::128:HMAC-SHA1:160:DEFAULT:0:rfc8422,rfc6347:0:0300:ffff
+c012:TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:ECDHE:RSA:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c013:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:ECDHE:RSA:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c014:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:ECDHE:RSA:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c015:TLS_ECDH_anon_WITH_NULL_SHA:ECDH:NULL:NULL::0:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c016:TLS_ECDH_anon_WITH_RC4_128_SHA:ECDH:NULL:RC4::128:HMAC-SHA1:160:DEFAULT:0:rfc8422,rfc6347:0:0300:ffff
+c017:TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:ECDH:NULL:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c018:TLS_ECDH_anon_WITH_AES_128_CBC_SHA:ECDH:NULL:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c019:TLS_ECDH_anon_WITH_AES_256_CBC_SHA:ECDH:NULL:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc8422:0:0300:ffff
+c01a:TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:SRP:SRP:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc5054:0:0300:ffff
+c01b:TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:SRP:SRP+RSA:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc5054:0:0300:ffff
+c01c:TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:SRP:SRP+DSS:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc5054:0:0300:ffff
+c01d:TLS_SRP_SHA_WITH_AES_128_CBC_SHA:SRP:SRP:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5054:0:0300:ffff
+c01e:TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:SRP:SRP+RSA:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5054:0:0300:ffff
+c01f:TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:SRP:SRP+DSS:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5054:0:0300:ffff
+c020:TLS_SRP_SHA_WITH_AES_256_CBC_SHA:SRP:SRP:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5054:0:0300:ffff
+c021:TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:SRP:SRP+RSA:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5054:0:0300:ffff
+c022:TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:SRP:SRP+DSS:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5054:0:0300:ffff
+c023:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:ECDHE:ECDSA:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5289:0:0300:ffff
+c024:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:ECDHE:ECDSA:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5289:0:0300:ffff
+c025:TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:ECDH:ECDSA:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5289:0:0300:ffff
+c026:TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:ECDH:ECDSA:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5289:0:0300:ffff
+c027:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:ECDHE:RSA:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5289:0:0300:ffff
+c028:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:ECDHE:RSA:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5289:0:0300:ffff
+c029:TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:ECDH:RSA:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5289:0:0300:ffff
+c02a:TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:ECDH:RSA:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5289:0:0300:ffff
+c02b:TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:ECDHE:ECDSA:AES:GCM:128:AEAD:128:SHA256:256:rfc5289:0:0300:ffff
+c02c:TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:ECDHE:ECDSA:AES:GCM:256:AEAD:256:SHA384:384:rfc5289:0:0300:ffff
+c02d:TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:ECDH:ECDSA:AES:GCM:128:AEAD:128:SHA256:256:rfc5289:0:0300:ffff
+c02e:TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:ECDH:ECDSA:AES:GCM:256:AEAD:256:SHA384:384:rfc5289:0:0300:ffff
+c02f:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:ECDHE:RSA:AES:GCM:128:AEAD:128:SHA256:256:rfc5289:0:0300:ffff
+c030:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:ECDHE:RSA:AES:GCM:256:AEAD:256:SHA384:384:rfc5289:0:0300:ffff
+c031:TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:ECDH:RSA:AES:GCM:128:AEAD:128:SHA256:256:rfc5289:0:0300:ffff
+c032:TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:ECDH:RSA:AES:GCM:256:AEAD:256:SHA384:384:rfc5289:0:0300:ffff
+c033:TLS_ECDHE_PSK_WITH_RC4_128_SHA:ECDHE:PSK:RC4::128:HMAC-SHA1:160:DEFAULT:0:rfc5489,rfc6347:0:0300:ffff
+c034:TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:ECDHE:PSK:3DES:CBC:168:HMAC-SHA1:160:DEFAULT:0:rfc5489:0:0300:ffff
+c035:TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:ECDHE:PSK:AES:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5489:0:0300:ffff
+c036:TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:ECDHE:PSK:AES:CBC:256:HMAC-SHA1:160:DEFAULT:0:rfc5489:0:0300:ffff
+c037:TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:ECDHE:PSK:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5489:0:0300:ffff
+c038:TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:ECDHE:PSK:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5489:0:0300:ffff
+c039:TLS_ECDHE_PSK_WITH_NULL_SHA:ECDHE:PSK:NULL::0:HMAC-SHA1:160:DEFAULT:0:rfc5489:0:0300:ffff
+c03a:TLS_ECDHE_PSK_WITH_NULL_SHA256:ECDHE:PSK:NULL::0:HMAC-SHA256:256:SHA256:256:rfc5489:0:0300:ffff
+c03b:TLS_ECDHE_PSK_WITH_NULL_SHA384:ECDHE:PSK:NULL::0:HMAC-SHA384:384:SHA384:384:rfc5489:0:0300:ffff
+c03c:TLS_RSA_WITH_ARIA_128_CBC_SHA256:RSA:RSA:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0300:ffff
+c03d:TLS_RSA_WITH_ARIA_256_CBC_SHA384:RSA:RSA:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0300:ffff
+c03e:TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256:DH:DSS:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0300:ffff
+c03f:TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384:DH:DSS:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0300:ffff
+c040:TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256:DH:RSA:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0300:ffff
+c041:TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384:DH:RSA:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0300:ffff
+c042:TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256:DHE:DSS:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0300:ffff
+c043:TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384:DHE:DSS:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0300:ffff
+c044:TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256:DHE:RSA:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0300:ffff
+c045:TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384:DHE:RSA:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0300:ffff
+c046:TLS_DH_anon_WITH_ARIA_128_CBC_SHA256:DH:NULL:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0300:ffff
+c047:TLS_DH_anon_WITH_ARIA_256_CBC_SHA384:DH:NULL:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0300:ffff
+c048:TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256:ECDHE:ECDSA:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0300:ffff
+c049:TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384:ECDHE:ECDSA:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0300:ffff
+c04a:TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256:ECDH:ECDSA:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0300:ffff
+c04b:TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384:ECDH:ECDSA:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0300:ffff
+c04c:TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256:ECDHE:RSA:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0300:ffff
+c04d:TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384:ECDHE:RSA:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0300:ffff
+c04e:TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256:ECDH:RSA:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0300:ffff
+c04f:TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384:ECDH:RSA:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0300:ffff
+c050:TLS_RSA_WITH_ARIA_128_GCM_SHA256:RSA:RSA:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0300:ffff
+c051:TLS_RSA_WITH_ARIA_256_GCM_SHA384:RSA:RSA:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0300:ffff
+c052:TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256:DHE:RSA:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0300:ffff
+c053:TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384:DHE:RSA:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0300:ffff
+c054:TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256:DH:RSA:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0300:ffff
+c055:TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384:DH:RSA:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0300:ffff
+c056:TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256:DHE:DSS:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0300:ffff
+c057:TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384:DHE:DSS:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0300:ffff
+c058:TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256:DH:DSS:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0300:ffff
+c059:TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384:DH:DSS:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0300:ffff
+c05a:TLS_DH_anon_WITH_ARIA_128_GCM_SHA256:DH:NULL:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0300:ffff
+c05b:TLS_DH_anon_WITH_ARIA_256_GCM_SHA384:DH:NULL:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0300:ffff
+c05c:TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256:ECDHE:ECDSA:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0300:ffff
+c05d:TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384:ECDHE:ECDSA:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0300:ffff
+c05e:TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256:ECDH:ECDSA:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0300:ffff
+c05f:TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384:ECDH:ECDSA:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0300:ffff
+c060:TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256:ECDHE:RSA:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0300:ffff
+c061:TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384:ECDHE:RSA:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0300:ffff
+c062:TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256:ECDH:RSA:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0300:ffff
+c063:TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384:ECDH:RSA:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0300:ffff
+c064:TLS_PSK_WITH_ARIA_128_CBC_SHA256:PSK:PSK:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0300:ffff
+c065:TLS_PSK_WITH_ARIA_256_CBC_SHA384:PSK:PSK:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0300:ffff
+c066:TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256:DHE:PSK:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0300:ffff
+c067:TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384:DHE:PSK:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0300:ffff
+c068:TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256:RSA:PSK:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0300:ffff
+c069:TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384:RSA:PSK:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0300:ffff
+c06a:TLS_PSK_WITH_ARIA_128_GCM_SHA256:PSK:PSK:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0300:ffff
+c06b:TLS_PSK_WITH_ARIA_256_GCM_SHA384:PSK:PSK:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0300:ffff
+c06c:TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256:DHE:PSK:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0300:ffff
+c06d:TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384:DHE:PSK:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0300:ffff
+c06e:TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256:RSA:PSK:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0300:ffff
+c06f:TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384:RSA:PSK:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0300:ffff
+c070:TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256:ECDHE:PSK:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0300:ffff
+c071:TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384:ECDHE:PSK:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0300:ffff
+c072:TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:ECDHE:ECDSA:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0300:ffff
+c073:TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:ECDHE:ECDSA:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0300:ffff
+c074:TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:ECDH:ECDSA:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0300:ffff
+c075:TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:ECDH:ECDSA:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0300:ffff
+c076:TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:ECDHE:RSA:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0300:ffff
+c077:TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:ECDHE:RSA:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0300:ffff
+c078:TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:ECDH:RSA:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0300:ffff
+c079:TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:ECDH:RSA:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0300:ffff
+c07a:TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:RSA:RSA:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0300:ffff
+c07b:TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:RSA:RSA:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0300:ffff
+c07c:TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:DHE:RSA:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0300:ffff
+c07d:TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:DHE:RSA:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0300:ffff
+c07e:TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:DH:RSA:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0300:ffff
+c07f:TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:DH:RSA:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0300:ffff
+c080:TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:DHE:DSS:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0300:ffff
+c081:TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:DHE:DSS:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0300:ffff
+c082:TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:DH:DSS:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0300:ffff
+c083:TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:DH:DSS:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0300:ffff
+c084:TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256:DH:NULL:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0300:ffff
+c085:TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384:DH:NULL:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0300:ffff
+c086:TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:ECDHE:ECDSA:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0300:ffff
+c087:TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:ECDHE:ECDSA:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0300:ffff
+c088:TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:ECDH:ECDSA:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0300:ffff
+c089:TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:ECDH:ECDSA:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0300:ffff
+c08a:TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:ECDHE:RSA:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0300:ffff
+c08b:TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:ECDHE:RSA:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0300:ffff
+c08c:TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:ECDH:RSA:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0300:ffff
+c08d:TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:ECDH:RSA:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0300:ffff
+c08e:TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:PSK:PSK:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0300:ffff
+c08f:TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:PSK:PSK:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0300:ffff
+c090:TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:DHE:PSK:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0300:ffff
+c091:TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:DHE:PSK:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0300:ffff
+c092:TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:RSA:PSK:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0300:ffff
+c093:TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:RSA:PSK:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0300:ffff
+c094:TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:PSK:PSK:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0300:ffff
+c095:TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:PSK:PSK:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0300:ffff
+c096:TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:DHE:PSK:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0300:ffff
+c097:TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:DHE:PSK:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0300:ffff
+c098:TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:RSA:PSK:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0300:ffff
+c099:TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:RSA:PSK:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0300:ffff
+c09a:TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:ECDHE:PSK:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0300:ffff
+c09b:TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:ECDHE:PSK:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0300:ffff
+c09c:TLS_RSA_WITH_AES_128_CCM:RSA:RSA:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0300:ffff
+c09d:TLS_RSA_WITH_AES_256_CCM:RSA:RSA:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0300:ffff
+c09e:TLS_DHE_RSA_WITH_AES_128_CCM:DHE:RSA:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0300:ffff
+c09f:TLS_DHE_RSA_WITH_AES_256_CCM:DHE:RSA:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0300:ffff
+c0a0:TLS_RSA_WITH_AES_128_CCM_8:RSA:RSA:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0300:ffff
+c0a1:TLS_RSA_WITH_AES_256_CCM_8:RSA:RSA:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0300:ffff
+c0a2:TLS_DHE_RSA_WITH_AES_128_CCM_8:DHE:RSA:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0300:ffff
+c0a3:TLS_DHE_RSA_WITH_AES_256_CCM_8:DHE:RSA:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0300:ffff
+c0a4:TLS_PSK_WITH_AES_128_CCM:PSK:PSK:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0300:ffff
+c0a5:TLS_PSK_WITH_AES_256_CCM:PSK:PSK:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0300:ffff
+c0a6:TLS_DHE_PSK_WITH_AES_128_CCM:DHE:PSK:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0300:ffff
+c0a7:TLS_DHE_PSK_WITH_AES_256_CCM:DHE:PSK:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0300:ffff
+c0a8:TLS_PSK_WITH_AES_128_CCM_8:PSK:PSK:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0300:ffff
+c0a9:TLS_PSK_WITH_AES_256_CCM_8:PSK:PSK:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0300:ffff
+c0aa:TLS_PSK_DHE_WITH_AES_128_CCM_8:PSK:DHE:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0300:ffff
+c0ab:TLS_PSK_DHE_WITH_AES_256_CCM_8:PSK:DHE:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0300:ffff
+c0ac:TLS_ECDHE_ECDSA_WITH_AES_128_CCM:ECDHE:ECDSA:AES:CCM:128:AEAD:128:DEFAULT:0:rfc7251:0:0300:ffff
+c0ad:TLS_ECDHE_ECDSA_WITH_AES_256_CCM:ECDHE:ECDSA:AES:CCM:256:AEAD:256:DEFAULT:0:rfc7251:0:0300:ffff
+c0ae:TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:ECDHE:ECDSA:AES:CCM:128:AEAD:128:DEFAULT:0:rfc7251:0:0300:ffff
+c0af:TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:ECDHE:ECDSA:AES:CCM:256:AEAD:256:DEFAULT:0:rfc7251:0:0300:ffff
+c0b0:TLS_ECCPWD_WITH_AES_128_GCM_SHA256:ECCPWD:ECCPWD:AES:GCM:128:AEAD:128:SHA256:256:rfc8492:0:0300:ffff
+c0b1:TLS_ECCPWD_WITH_AES_256_GCM_SHA384:ECCPWD:ECCPWD:AES:GCM:256:AEAD:256:SHA384:384:rfc8492:0:0300:ffff
+c0b2:TLS_ECCPWD_WITH_AES_128_CCM_SHA256:ECCPWD:ECCPWD:AES:CCM:128:AEAD:128:SHA256:256:rfc8492:0:0300:ffff
+c0b3:TLS_ECCPWD_WITH_AES_256_CCM_SHA384:ECCPWD:ECCPWD:AES:CCM:256:AEAD:256:SHA384:384:rfc8492:0:0300:ffff
+c0b4:TLS_SHA256_SHA256:TLS13:TLS13:NULL::0:HMAC-SHA256:256:SHA256:256:rfc-camwinget-tls-ts13-macciphersuites-12:0:0300:ffff
+c0b5:TLS_SHA384_SHA384:TLS13:TLS13:NULL::0:HMAC-SHA384:384:SHA384:384:rfc-camwinget-tls-ts13-macciphersuites-12:0:0300:ffff
+cca8:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:ECDHE:RSA:CHACHA20_POLY1305::128:AEAD:128:SHA256:256:rfc7905:0:0300:ffff
+cca9:TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:ECDHE:ECDSA:CHACHA20_POLY1305::128:AEAD:128:SHA256:256:rfc7905:0:0300:ffff
+ccaa:TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:DHE:RSA:CHACHA20_POLY1305::128:AEAD:128:SHA256:256:rfc7905:0:0300:ffff
+ccab:TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:PSK:PSK:CHACHA20_POLY1305::128:AEAD:128:SHA256:256:rfc7905:0:0300:ffff
+ccac:TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:ECDHE:PSK:CHACHA20_POLY1305::128:AEAD:128:SHA256:256:rfc7905:0:0300:ffff
+ccad:TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:DHE:PSK:CHACHA20_POLY1305::128:AEAD:128:SHA256:256:rfc7905:0:0300:ffff
+ccae:TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256:RSA:PSK:CHACHA20_POLY1305::128:AEAD:128:SHA256:256:rfc7905:0:0300:ffff
+d001:TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256:ECDHE:PSK:AES:GCM:128:AEAD:128:SHA256:256:rfc8442:0:0300:ffff
+d002:TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384:ECDHE:PSK:AES:GCM:256:AEAD:256:SHA384:384:rfc8442:0:0300:ffff
+d003:TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256:ECDHE:PSK:AES:CCM:128:AEAD:128:SHA256:256:rfc8442:0:0300:ffff
+d005:TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256:ECDHE:PSK:AES:CCM:128:AEAD:128:SHA256:256:rfc8442:0:0300:ffff
diff --git a/rust/vendor/tls-parser/src/certificate_transparency.rs b/rust/vendor/tls-parser/src/certificate_transparency.rs
new file mode 100644
index 0000000..e25ccb5
--- /dev/null
+++ b/rust/vendor/tls-parser/src/certificate_transparency.rs
@@ -0,0 +1,111 @@
+///!
+///! Certificate Trasparency structures are defined in
+///! [RFC6962](https://datatracker.ietf.org/doc/html/rfc6962).
+use alloc::vec::Vec;
+use core::convert::TryInto;
+
+use nom::{
+ bytes::streaming::take,
+ combinator::{complete, map_parser},
+ multi::{length_data, many0},
+ number::streaming::{be_u16, be_u64, be_u8},
+ IResult,
+};
+use nom_derive::*;
+use rusticata_macros::newtype_enum;
+
+use crate::{parse_digitally_signed, DigitallySigned};
+
+/// Certificate Transparency Version as defined in [RFC6962 Section 3.2]
+/// (https://datatracker.ietf.org/doc/html/rfc6962#section-3.2)
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Nom)]
+pub struct CtVersion(pub u8);
+
+newtype_enum! {
+impl display CtVersion {
+ V1 = 0,
+}
+}
+
+/// LogID as defined in [RFC6962 Section 3.2]
+/// (https://datatracker.ietf.org/doc/html/rfc6962#section-3.2)
+#[derive(Clone, Debug, PartialEq)]
+pub struct CtLogID<'a> {
+ pub key_id: &'a [u8; 32],
+}
+
+/// CtExtensions as defined in [RFC6962 Section 3.2]
+/// (https://datatracker.ietf.org/doc/html/rfc6962#section-3.2)
+#[derive(Clone, Debug, PartialEq)]
+pub struct CtExtensions<'a>(pub &'a [u8]);
+
+/// Signed Certificate Timestamp as defined in [RFC6962 Section 3.2]
+/// (https://datatracker.ietf.org/doc/html/rfc6962#section-3.2)
+#[derive(Clone, Debug, PartialEq)]
+pub struct SignedCertificateTimestamp<'a> {
+ pub version: CtVersion,
+ pub id: CtLogID<'a>,
+ pub timestamp: u64,
+ pub extensions: CtExtensions<'a>,
+ pub signature: DigitallySigned<'a>,
+}
+
+pub(crate) fn parse_log_id(i: &[u8]) -> IResult<&[u8], CtLogID> {
+ let (i, key_id) = take(32usize)(i)?;
+ Ok((
+ i,
+ CtLogID {
+ key_id: key_id
+ .try_into()
+ .expect("take(32) is in sync with key_id size"),
+ },
+ ))
+}
+
+pub(crate) fn parse_ct_extensions(i: &[u8]) -> IResult<&[u8], CtExtensions> {
+ let (i, ext_len) = be_u16(i)?;
+ let (i, ext_data) = take(ext_len as usize)(i)?;
+ Ok((i, CtExtensions(ext_data)))
+}
+
+pub(crate) fn parse_ct_signed_certificate_timestamp_content(
+ i: &[u8],
+) -> IResult<&[u8], SignedCertificateTimestamp> {
+ let (i, version) = be_u8(i)?;
+ let (i, id) = parse_log_id(i)?;
+ let (i, timestamp) = be_u64(i)?;
+ let (i, extensions) = parse_ct_extensions(i)?;
+ let (i, signature) = parse_digitally_signed(i)?;
+ Ok((
+ i,
+ SignedCertificateTimestamp {
+ version: CtVersion(version),
+ id,
+ timestamp,
+ extensions,
+ signature,
+ },
+ ))
+}
+
+/// Parses as single Signed Certificate Timestamp entry
+pub fn parse_ct_signed_certificate_timestamp(
+ i: &[u8],
+) -> IResult<&[u8], SignedCertificateTimestamp> {
+ map_parser(
+ length_data(be_u16),
+ parse_ct_signed_certificate_timestamp_content,
+ )(i)
+}
+
+/// Parses a list of Signed Certificate Timestamp entries
+pub fn parse_ct_signed_certificate_timestamp_list(
+ i: &[u8],
+) -> IResult<&[u8], Vec<SignedCertificateTimestamp>> {
+ let (i, sct_len) = be_u16(i)?;
+ let (i, sct_list) = map_parser(
+ take(sct_len as usize),
+ many0(complete(parse_ct_signed_certificate_timestamp)),
+ )(i)?;
+ Ok((i, sct_list))
+}
diff --git a/rust/vendor/tls-parser/src/dtls.rs b/rust/vendor/tls-parser/src/dtls.rs
new file mode 100644
index 0000000..9c05738
--- /dev/null
+++ b/rust/vendor/tls-parser/src/dtls.rs
@@ -0,0 +1,314 @@
+//! Datagram Transport Layer Security Version 1.2 (RFC 6347)
+
+use crate::tls::*;
+use crate::TlsMessageAlert;
+use alloc::vec::Vec;
+use nom::bytes::streaming::take;
+use nom::combinator::{complete, cond, map, map_parser, opt, verify};
+use nom::error::{make_error, ErrorKind};
+use nom::multi::{length_data, many1};
+use nom::number::streaming::{be_u16, be_u24, be_u64, be_u8};
+use nom_derive::Parse;
+
+/// DTLS Plaintext record header
+#[derive(Debug, PartialEq)]
+pub struct DTLSRecordHeader {
+ pub content_type: TlsRecordType,
+ pub version: TlsVersion,
+ /// A counter value that is incremented on every cipher state change.
+ pub epoch: u16,
+ /// The sequence number for this record.
+ pub sequence_number: u64, // really an u48
+ pub length: u16,
+}
+
+/// DTLS Plaintext record
+///
+/// Each DTLS record MUST fit within a single datagram.
+///
+/// Multiple DTLS records may be placed in a single datagram.
+#[derive(Debug, PartialEq)]
+pub struct DTLSPlaintext<'a> {
+ pub header: DTLSRecordHeader,
+ pub messages: Vec<DTLSMessage<'a>>,
+}
+
+#[derive(Debug, PartialEq)]
+pub struct DTLSRawRecord<'a> {
+ pub header: DTLSRecordHeader,
+ pub fragment: &'a [u8],
+}
+
+#[derive(Debug, PartialEq)]
+pub struct DTLSClientHello<'a> {
+ pub version: TlsVersion,
+ pub random: &'a [u8],
+ pub session_id: Option<&'a [u8]>,
+ pub cookie: &'a [u8],
+ /// A list of ciphers supported by client
+ pub ciphers: Vec<TlsCipherSuiteID>,
+ /// A list of compression methods supported by client
+ pub comp: Vec<TlsCompressionID>,
+ pub ext: Option<&'a [u8]>,
+}
+
+impl<'a> ClientHello<'a> for DTLSClientHello<'a> {
+ fn version(&self) -> TlsVersion {
+ self.version
+ }
+
+ fn rand_data(&self) -> &'a [u8] {
+ self.random
+ }
+
+ fn session_id(&self) -> Option<&'a [u8]> {
+ self.session_id
+ }
+
+ fn ciphers(&self) -> &Vec<TlsCipherSuiteID> {
+ &self.ciphers
+ }
+
+ fn comp(&self) -> &Vec<TlsCompressionID> {
+ &self.comp
+ }
+
+ fn ext(&self) -> Option<&'a [u8]> {
+ self.ext
+ }
+}
+
+#[derive(Debug, PartialEq)]
+pub struct DTLSHelloVerifyRequest<'a> {
+ pub server_version: TlsVersion,
+ pub cookie: &'a [u8],
+}
+
+/// DTLS Generic handshake message
+#[derive(Debug, PartialEq)]
+pub struct DTLSMessageHandshake<'a> {
+ pub msg_type: TlsHandshakeType,
+ pub length: u32,
+ pub message_seq: u16,
+ pub fragment_offset: u32,
+ pub fragment_length: u32,
+ pub body: DTLSMessageHandshakeBody<'a>,
+}
+
+/// DTLS Generic handshake message
+#[derive(Debug, PartialEq)]
+pub enum DTLSMessageHandshakeBody<'a> {
+ HelloRequest,
+ ClientHello(DTLSClientHello<'a>),
+ HelloVerifyRequest(DTLSHelloVerifyRequest<'a>),
+ ServerHello(TlsServerHelloContents<'a>),
+ NewSessionTicket(TlsNewSessionTicketContent<'a>),
+ HelloRetryRequest(TlsHelloRetryRequestContents<'a>),
+ Certificate(TlsCertificateContents<'a>),
+ ServerKeyExchange(TlsServerKeyExchangeContents<'a>),
+ CertificateRequest(TlsCertificateRequestContents<'a>),
+ ServerDone(&'a [u8]),
+ CertificateVerify(&'a [u8]),
+ ClientKeyExchange(TlsClientKeyExchangeContents<'a>),
+ Finished(&'a [u8]),
+ CertificateStatus(TlsCertificateStatusContents<'a>),
+ NextProtocol(TlsNextProtocolContent<'a>),
+}
+
+/// DTLS plaintext message
+///
+/// Plaintext records can only be found during the handshake.
+#[derive(Debug, PartialEq)]
+pub enum DTLSMessage<'a> {
+ Handshake(DTLSMessageHandshake<'a>),
+ ChangeCipherSpec,
+ Alert(TlsMessageAlert),
+ ApplicationData(TlsMessageApplicationData<'a>),
+ Heartbeat(TlsMessageHeartbeat<'a>),
+}
+
+// --------------------------- PARSERS ---------------------------
+
+/// DTLS record header
+// Section 4.1 of RFC6347
+pub fn parse_dtls_record_header(i: &[u8]) -> IResult<&[u8], DTLSRecordHeader> {
+ let (i, content_type) = TlsRecordType::parse(i)?;
+ let (i, version) = TlsVersion::parse(i)?;
+ let (i, int0) = be_u64(i)?;
+ let epoch = (int0 >> 48) as u16;
+ let sequence_number = int0 & 0xffff_ffff_ffff;
+ let (i, length) = be_u16(i)?;
+ let record = DTLSRecordHeader {
+ content_type,
+ version,
+ epoch,
+ sequence_number,
+ length,
+ };
+ Ok((i, record))
+}
+
+/// DTLS Client Hello
+// Section 4.2 of RFC6347
+fn parse_dtls_client_hello(i: &[u8]) -> IResult<&[u8], DTLSMessageHandshakeBody> {
+ let (i, version) = TlsVersion::parse(i)?;
+ let (i, random) = take(32usize)(i)?;
+ let (i, sidlen) = verify(be_u8, |&n| n <= 32)(i)?;
+ let (i, session_id) = cond(sidlen > 0, take(sidlen as usize))(i)?;
+ let (i, cookie) = length_data(be_u8)(i)?;
+ let (i, ciphers_len) = be_u16(i)?;
+ let (i, ciphers) = parse_cipher_suites(i, ciphers_len as usize)?;
+ let (i, comp_len) = be_u8(i)?;
+ let (i, comp) = parse_compressions_algs(i, comp_len as usize)?;
+ let (i, ext) = opt(complete(length_data(be_u16)))(i)?;
+ let content = DTLSClientHello {
+ version,
+ random,
+ session_id,
+ cookie,
+ ciphers,
+ comp,
+ ext,
+ };
+ Ok((i, DTLSMessageHandshakeBody::ClientHello(content)))
+}
+
+/// DTLS Client Hello
+// Section 4.2 of RFC6347
+fn parse_dtls_hello_verify_request(i: &[u8]) -> IResult<&[u8], DTLSMessageHandshakeBody> {
+ let (i, server_version) = TlsVersion::parse(i)?;
+ let (i, cookie) = length_data(be_u8)(i)?;
+ let content = DTLSHelloVerifyRequest {
+ server_version,
+ cookie,
+ };
+ Ok((i, DTLSMessageHandshakeBody::HelloVerifyRequest(content)))
+}
+
+fn parse_dtls_handshake_msg_server_hello_tlsv12(
+ i: &[u8],
+) -> IResult<&[u8], DTLSMessageHandshakeBody> {
+ map(
+ parse_tls_server_hello_tlsv12,
+ DTLSMessageHandshakeBody::ServerHello,
+ )(i)
+}
+
+fn parse_dtls_handshake_msg_serverdone(
+ i: &[u8],
+ len: usize,
+) -> IResult<&[u8], DTLSMessageHandshakeBody> {
+ map(take(len), DTLSMessageHandshakeBody::ServerDone)(i)
+}
+
+fn parse_dtls_handshake_msg_clientkeyexchange(
+ i: &[u8],
+ len: usize,
+) -> IResult<&[u8], DTLSMessageHandshakeBody> {
+ map(
+ parse_tls_clientkeyexchange(len),
+ DTLSMessageHandshakeBody::ClientKeyExchange,
+ )(i)
+}
+
+fn parse_dtls_handshake_msg_certificate(i: &[u8]) -> IResult<&[u8], DTLSMessageHandshakeBody> {
+ map(parse_tls_certificate, DTLSMessageHandshakeBody::Certificate)(i)
+}
+
+/// Parse a DTLS handshake message
+pub fn parse_dtls_message_handshake(i: &[u8]) -> IResult<&[u8], DTLSMessage> {
+ let (i, msg_type) = map(be_u8, TlsHandshakeType)(i)?;
+ let (i, length) = be_u24(i)?;
+ let (i, message_seq) = be_u16(i)?;
+ let (i, fragment_offset) = be_u24(i)?;
+ let (i, fragment_length) = be_u24(i)?;
+ let (i, raw_msg) = take(length)(i)?;
+ let (_, body) = match msg_type {
+ TlsHandshakeType::ClientHello => parse_dtls_client_hello(raw_msg),
+ TlsHandshakeType::HelloVerifyRequest => parse_dtls_hello_verify_request(raw_msg),
+ TlsHandshakeType::ServerHello => parse_dtls_handshake_msg_server_hello_tlsv12(raw_msg),
+ TlsHandshakeType::ServerDone => {
+ parse_dtls_handshake_msg_serverdone(raw_msg, length as usize)
+ }
+ TlsHandshakeType::ClientKeyExchange => {
+ parse_dtls_handshake_msg_clientkeyexchange(raw_msg, length as usize)
+ }
+ TlsHandshakeType::Certificate => parse_dtls_handshake_msg_certificate(raw_msg),
+ _ => {
+ // eprintln!("Unsupported message type {:?}", msg_type);
+ Err(Err::Error(make_error(i, ErrorKind::Switch)))
+ }
+ }?;
+ let msg = DTLSMessageHandshake {
+ msg_type,
+ length,
+ message_seq,
+ fragment_offset,
+ fragment_length,
+ body,
+ };
+ Ok((i, DTLSMessage::Handshake(msg)))
+}
+
+/// Parse a DTLS changecipherspec message
+// XXX add extra verification hdr.len == 1
+pub fn parse_dtls_message_changecipherspec(i: &[u8]) -> IResult<&[u8], DTLSMessage> {
+ let (i, _) = verify(be_u8, |&tag| tag == 0x01)(i)?;
+ Ok((i, DTLSMessage::ChangeCipherSpec))
+}
+
+/// Parse a DTLS alert message
+// XXX add extra verification hdr.len == 2
+pub fn parse_dtls_message_alert(i: &[u8]) -> IResult<&[u8], DTLSMessage> {
+ let (i, alert) = TlsMessageAlert::parse(i)?;
+ Ok((i, DTLSMessage::Alert(alert)))
+}
+
+pub fn parse_dtls_record_with_header<'i, 'hdr>(
+ i: &'i [u8],
+ hdr: &'hdr DTLSRecordHeader,
+) -> IResult<&'i [u8], Vec<DTLSMessage<'i>>> {
+ match hdr.content_type {
+ TlsRecordType::ChangeCipherSpec => many1(complete(parse_dtls_message_changecipherspec))(i),
+ TlsRecordType::Alert => many1(complete(parse_dtls_message_alert))(i),
+ TlsRecordType::Handshake => many1(complete(parse_dtls_message_handshake))(i),
+ // TlsRecordType::ApplicationData => many1(complete(parse_tls_message_applicationdata))(i),
+ // TlsRecordType::Heartbeat => parse_tls_message_heartbeat(i, hdr.length),
+ _ => {
+ // eprintln!("Unsupported record type {:?}", hdr.content_type);
+ Err(Err::Error(make_error(i, ErrorKind::Switch)))
+ }
+ }
+}
+
+/// Parse DTLS record, leaving `fragment` unparsed
+// Section 4.1 of RFC6347
+pub fn parse_dtls_raw_record(i: &[u8]) -> IResult<&[u8], DTLSRawRecord> {
+ let (i, header) = parse_dtls_record_header(i)?;
+ // As in TLS 1.2, the length should not exceed 2^14.
+ if header.length > MAX_RECORD_LEN {
+ return Err(Err::Error(make_error(i, ErrorKind::TooLarge)));
+ }
+ let (i, fragment) = take(header.length as usize)(i)?;
+ Ok((i, DTLSRawRecord { header, fragment }))
+}
+
+/// Parse one DTLS plaintext record
+// Section 4.1 of RFC6347
+pub fn parse_dtls_plaintext_record(i: &[u8]) -> IResult<&[u8], DTLSPlaintext> {
+ let (i, header) = parse_dtls_record_header(i)?;
+ // As in TLS 1.2, the length should not exceed 2^14.
+ if header.length > MAX_RECORD_LEN {
+ return Err(Err::Error(make_error(i, ErrorKind::TooLarge)));
+ }
+ let (i, messages) = map_parser(take(header.length as usize), |i| {
+ parse_dtls_record_with_header(i, &header)
+ })(i)?;
+ Ok((i, DTLSPlaintext { header, messages }))
+}
+
+/// Parse multiple DTLS plaintext record
+// Section 4.1 of RFC6347
+pub fn parse_dtls_plaintext_records(i: &[u8]) -> IResult<&[u8], Vec<DTLSPlaintext>> {
+ many1(complete(parse_dtls_plaintext_record))(i)
+}
diff --git a/rust/vendor/tls-parser/src/lib.rs b/rust/vendor/tls-parser/src/lib.rs
new file mode 100644
index 0000000..422197e
--- /dev/null
+++ b/rust/vendor/tls-parser/src/lib.rs
@@ -0,0 +1,175 @@
+//! [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE-MIT)
+//! [![Apache License 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE-APACHE)
+//! [![Crates.io Version](https://img.shields.io/crates/v/tls-parser.svg)](https://crates.io/crates/tls-parser)
+//! [![Github CI](https://github.com/rusticata/der-parser/workflows/Continuous%20integration/badge.svg)](https://github.com/rusticata/der-parser/actions)
+//! [![Minimum rustc version](https://img.shields.io/badge/rustc-1.46.0+-lightgray.svg)](#rust-version-requirements)
+//!
+//! # TLS Parser
+//!
+//! A TLS parser, implemented with the [nom](https://github.com/Geal/nom)
+//! parser combinator framework.
+//!
+//! The goal of this parser is to implement TLS messages analysis, for example
+//! to use rules from a network IDS, for ex during the TLS handshake.
+//!
+//! It implements structures and parsing functions for records and messages, but
+//! need additional code to handle fragmentation, or to fully inspect messages.
+//! Parsing some TLS messages requires to know the previously selected parameters.
+//! See [the rusticata TLS parser](https://github.com/rusticata/rusticata/blob/master/src/tls.rs)
+//! for a full example.
+//!
+//! It is written in pure Rust, fast, and makes extensive use of zero-copy. A lot of care is taken
+//! to ensure security and safety of this crate, including design (recursion limit, defensive
+//! programming), tests, and fuzzing. It also aims to be panic-free.
+//!
+//! The code is available on [Github](https://github.com/rusticata/tls-parser)
+//! and is part of the [Rusticata](https://github.com/rusticata) project.
+//!
+//! ## Parsing records
+//!
+//! The main parsing functions are located in the [tls.rs](src/tls.rs) file. The entry functions are:
+//! - `parse_tls_plaintext`: parses a record as plaintext
+//! - `parse_tls_encrypted`: read an encrypted record. The parser has no crypto or decryption features, so the content
+//! will be left as opaque data.
+//!
+//! # Examples
+//!
+//! ```rust
+//! use tls_parser::parse_tls_plaintext;
+//! use tls_parser::nom::{Err, IResult};
+//!
+//! let bytes : &[u8]= include_bytes!("../assets/client_hello_dhe.bin");
+//! // [ 0x16, 0x03, 0x01 ... ];
+//! let res = parse_tls_plaintext(&bytes);
+//! match res {
+//! Ok((rem,record)) => {
+//! // rem is the remaining data (not parsed)
+//! // record is an object of type TlsRecord
+//! },
+//! Err(Err::Incomplete(needed)) => {
+//! eprintln!("Defragmentation required (TLS record)");
+//! },
+//! Err(e) => { eprintln!("parse_tls_record_with_header failed: {:?}",e); }
+//! }
+//! ```
+//!
+//! Note that knowing if a record is plaintext or not is the responsibility of the caller.
+//!
+//! As reading TLS records may imply defragmenting records, some functions are
+//! provided to only read the record as opaque data (which ensures the record is
+//! complete and gives the record header) and then reading messages from data.
+//!
+//! Here is an example of two-steps parsing:
+//!
+//! ```rust
+//! # use tls_parser::{parse_tls_raw_record, parse_tls_record_with_header};
+//! # use tls_parser::nom::{Err, IResult};
+//!
+//! # let bytes : &[u8]= include_bytes!("../assets/client_hello_dhe.bin");
+//! // [ 0x16, 0x03, 0x01 ... ];
+//! match parse_tls_raw_record(bytes) {
+//! Ok((rem, ref r)) => {
+//! match parse_tls_record_with_header(r.data, &r.hdr) {
+//! Ok((rem2,ref msg_list)) => {
+//! for msg in msg_list {
+//! // msg has type TlsMessage
+//! }
+//! }
+//! Err(Err::Incomplete(needed)) => { eprintln!("incomplete record") }
+//! Err(_) => { eprintln!("error while parsing record") }
+//! }
+//! }
+//! Err(Err::Incomplete(needed)) => { eprintln!("incomplete record header") }
+//! Err(_) => { eprintln!("error while parsing record header") }
+//! }
+//! ```
+//!
+//! Some additional work is required if reading packets from the network, to support
+//! reassembly of TCP segments and reassembly of TLS records.
+//!
+//! For a complete example of a TLS parser supporting defragmentation and states, see the
+//! [rusticata/src/tls.rs](https://github.com/rusticata/rusticata/blob/master/src/tls.rs) file of
+//! the [rusticata](https://github.com/rusticata/rusticata) crate.
+//!
+//! ## State machine
+//!
+//! A TLS state machine is provided in [tls_states.rs](src/tls_states.rs). The state machine is separated from the
+//! parsing functions, and is almost independent.
+//! It is implemented as a table of transitions, mainly for the handshake phase.
+//!
+//! After reading a TLS message using the previous functions, the TLS state can be
+//! updated using the `tls_state_transition` function. If the transition succeeds,
+//! it returns `Ok(new_state)`, otherwise it returns `Err(error_state)`.
+//!
+//! ```rust
+//! # use tls_parser::{tls_state_transition, TlsMessage, TlsState};
+//! # use tls_parser::nom::{Err, IResult};
+//!
+//! struct ParseContext {
+//! state: TlsState,
+//! }
+//!
+//! # fn update_state_machine(msg: &TlsMessage, ctx: &mut ParseContext, to_server:bool) -> Result<(),&'static str> {
+//! match tls_state_transition(ctx.state, msg, to_server) {
+//! Ok(s) => { ctx.state = s; Ok(()) }
+//! Err(_) => {
+//! ctx.state = TlsState::Invalid;
+//! Err("Invalid state")
+//! }
+//! }
+//! # }
+//! ```
+//!
+//! # Implementation notes
+//!
+//! When parsing messages, if a field is an integer corresponding to an enum of known values,
+//! it is not parsed as an enum type, but as an integer. While this complicates accesses,
+//! it allows to read invalid values and continue parsing (for an IDS, it's better to read
+//! values than to get a generic parse error).
+
+#![deny(/*missing_docs,*/
+ unstable_features,
+ /*unused_import_braces,*/ unused_qualifications)]
+#![forbid(unsafe_code)]
+#![allow(clippy::upper_case_acronyms)]
+#![no_std]
+
+#[cfg(any(test, feature = "std"))]
+#[macro_use]
+extern crate std;
+
+extern crate alloc;
+
+mod certificate_transparency;
+mod dtls;
+mod tls;
+mod tls_alert;
+mod tls_ciphers;
+mod tls_debug;
+mod tls_dh;
+mod tls_ec;
+mod tls_extensions;
+mod tls_sign_hash;
+mod tls_states;
+
+pub use certificate_transparency::*;
+pub use dtls::*;
+pub use tls::*;
+pub use tls_alert::*;
+pub use tls_ciphers::*;
+pub use tls_dh::*;
+pub use tls_ec::*;
+pub use tls_extensions::*;
+pub use tls_sign_hash::*;
+pub use tls_states::*;
+
+#[cfg(all(feature = "serialize", not(feature = "std")))]
+compile_error!("features `serialize` cannot be enable when using `no_std`");
+
+#[cfg(all(feature = "serialize", feature = "std"))]
+mod tls_serialize;
+#[cfg(feature = "serialize")]
+pub use tls_serialize::*;
+
+pub use nom;
+pub use rusticata_macros;
diff --git a/rust/vendor/tls-parser/src/tls.rs b/rust/vendor/tls-parser/src/tls.rs
new file mode 100644
index 0000000..ffd3f5b
--- /dev/null
+++ b/rust/vendor/tls-parser/src/tls.rs
@@ -0,0 +1,977 @@
+//! # TLS parser
+//! Parsing functions for the TLS protocol, supporting versions 1.0 to 1.3
+
+use alloc::{vec, vec::Vec};
+use core::convert::AsRef;
+use core::fmt;
+use core::ops::Deref;
+use nom::branch::alt;
+use nom::bytes::streaming::take;
+use nom::combinator::{complete, cond, map, map_parser, opt, verify};
+use nom::error::{make_error, ErrorKind};
+use nom::multi::{length_count, length_data, many0, many1};
+use nom::number::streaming::{be_u16, be_u24, be_u32, be_u8};
+use nom_derive::*;
+use rusticata_macros::newtype_enum;
+
+use crate::tls_alert::*;
+use crate::tls_ciphers::*;
+use crate::tls_ec::ECPoint;
+
+pub use nom::{Err, IResult};
+
+/// Max record size (RFC8446 5.1)
+pub const MAX_RECORD_LEN: u16 = 1 << 14;
+
+/// Handshake type
+///
+/// Handshake types are defined in [RFC5246](https://tools.ietf.org/html/rfc5246) and
+/// the [IANA HandshakeType
+/// Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-7)
+#[derive(Clone, Copy, PartialEq, Eq, NomBE)]
+pub struct TlsHandshakeType(pub u8);
+
+newtype_enum! {
+impl debug TlsHandshakeType {
+ HelloRequest = 0x00,
+ ClientHello = 0x01,
+ ServerHello = 0x02,
+ HelloVerifyRequest = 0x03,
+ NewSessionTicket = 0x04,
+ EndOfEarlyData = 0x05,
+ HelloRetryRequest = 0x06,
+ EncryptedExtensions = 0x08,
+ Certificate = 0x0b,
+ ServerKeyExchange = 0x0c,
+ CertificateRequest = 0x0d,
+ ServerDone = 0x0e,
+ CertificateVerify = 0x0f,
+ ClientKeyExchange = 0x10,
+ Finished = 0x14,
+ CertificateURL = 0x15,
+ CertificateStatus = 0x16,
+ KeyUpdate = 0x18,
+
+ NextProtocol = 0x43,
+}
+}
+
+impl From<TlsHandshakeType> for u8 {
+ fn from(v: TlsHandshakeType) -> u8 {
+ v.0
+ }
+}
+
+/// TLS version
+///
+/// Only the TLS version defined in the TLS message header is meaningful, the
+/// version defined in the record should be ignored or set to TLS 1.0
+#[derive(Clone, Copy, PartialEq, Eq, NomBE)]
+pub struct TlsVersion(pub u16);
+
+newtype_enum! {
+impl debug TlsVersion {
+ Ssl30 = 0x0300,
+ Tls10 = 0x0301,
+ Tls11 = 0x0302,
+ Tls12 = 0x0303,
+ Tls13 = 0x0304,
+
+ Tls13Draft18 = 0x7f12,
+ Tls13Draft19 = 0x7f13,
+ Tls13Draft20 = 0x7f14,
+ Tls13Draft21 = 0x7f15,
+ Tls13Draft22 = 0x7f16,
+ Tls13Draft23 = 0x7f17,
+
+ DTls10 = 0xfeff,
+ DTls11 = 0xfefe,
+ DTls12 = 0xfefd,
+}
+}
+
+impl From<TlsVersion> for u16 {
+ fn from(v: TlsVersion) -> u16 {
+ v.0
+ }
+}
+
+impl fmt::LowerHex for TlsVersion {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{:x}", self.0)
+ }
+}
+
+/// Heartbeat type, as defined in [RFC6520](https://tools.ietf.org/html/rfc6520) section 3
+#[derive(Clone, Copy, PartialEq, Eq, NomBE)]
+pub struct TlsHeartbeatMessageType(pub u8);
+
+newtype_enum! {
+impl debug TlsHeartbeatMessageType {
+ HeartBeatRequest = 0x1,
+ HeartBeatResponse = 0x2,
+}
+}
+
+impl From<TlsHeartbeatMessageType> for u8 {
+ fn from(v: TlsHeartbeatMessageType) -> u8 {
+ v.0
+ }
+}
+
+/// Content type, as defined in IANA TLS ContentType registry
+#[derive(Clone, Copy, PartialEq, Eq, NomBE)]
+pub struct TlsRecordType(pub u8);
+
+newtype_enum! {
+impl debug TlsRecordType {
+ ChangeCipherSpec = 0x14,
+ Alert = 0x15,
+ Handshake = 0x16,
+ ApplicationData = 0x17,
+ Heartbeat = 0x18,
+}
+}
+
+impl From<TlsRecordType> for u8 {
+ fn from(v: TlsRecordType) -> u8 {
+ v.0
+ }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, NomBE)]
+pub struct TlsCompressionID(pub u8);
+
+newtype_enum! {
+impl debug TlsCompressionID {
+ Null = 0x00,
+}
+}
+
+impl From<TlsCompressionID> for u8 {
+ fn from(c: TlsCompressionID) -> u8 {
+ c.0
+ }
+}
+
+impl Deref for TlsCompressionID {
+ type Target = u8;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl AsRef<u8> for TlsCompressionID {
+ fn as_ref(&self) -> &u8 {
+ &self.0
+ }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, NomBE)]
+pub struct TlsCipherSuiteID(pub u16);
+
+impl TlsCipherSuiteID {
+ pub fn get_ciphersuite(self) -> Option<&'static TlsCipherSuite> {
+ TlsCipherSuite::from_id(self.0)
+ }
+}
+
+impl From<TlsCipherSuiteID> for u16 {
+ fn from(c: TlsCipherSuiteID) -> u16 {
+ c.0
+ }
+}
+
+impl Deref for TlsCipherSuiteID {
+ type Target = u16;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl AsRef<u16> for TlsCipherSuiteID {
+ fn as_ref(&self) -> &u16 {
+ &self.0
+ }
+}
+
+impl fmt::Display for TlsCipherSuiteID {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.0)
+ }
+}
+
+impl fmt::Debug for TlsCipherSuiteID {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match TlsCipherSuite::from_id(self.0) {
+ Some(c) => write!(f, "0x{:04x}({})", self.0, c.name),
+ None => write!(f, "0x{:04x}(Unknown cipher)", self.0),
+ }
+ }
+}
+
+impl fmt::LowerHex for TlsCipherSuiteID {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{:x}", self.0)
+ }
+}
+
+/// A trait that both TLS & DTLS satisfy
+pub trait ClientHello<'a> {
+ /// TLS version of message
+ fn version(&self) -> TlsVersion;
+ fn rand_data(&self) -> &'a [u8];
+ fn session_id(&self) -> Option<&'a [u8]>;
+ /// A list of ciphers supported by client
+ fn ciphers(&self) -> &Vec<TlsCipherSuiteID>;
+ fn cipher_suites(&self) -> Vec<Option<&'static TlsCipherSuite>> {
+ self.ciphers()
+ .iter()
+ .map(|&x| x.get_ciphersuite())
+ .collect()
+ }
+ /// A list of compression methods supported by client
+ fn comp(&self) -> &Vec<TlsCompressionID>;
+ fn ext(&self) -> Option<&'a [u8]>;
+}
+
+/// TLS Client Hello (from TLS 1.0 to TLS 1.2)
+///
+/// Some fields are unparsed (for performance reasons), for ex to parse `ext`,
+/// call the `parse_tls_extensions` function.
+#[derive(Clone, PartialEq)]
+pub struct TlsClientHelloContents<'a> {
+ /// TLS version of message
+ pub version: TlsVersion,
+ pub rand_time: u32,
+ pub rand_data: &'a [u8],
+ pub session_id: Option<&'a [u8]>,
+ /// A list of ciphers supported by client
+ pub ciphers: Vec<TlsCipherSuiteID>,
+ /// A list of compression methods supported by client
+ pub comp: Vec<TlsCompressionID>,
+
+ pub ext: Option<&'a [u8]>,
+}
+
+impl<'a> TlsClientHelloContents<'a> {
+ pub fn new(
+ v: u16,
+ rt: u32,
+ rd: &'a [u8],
+ sid: Option<&'a [u8]>,
+ c: Vec<TlsCipherSuiteID>,
+ co: Vec<TlsCompressionID>,
+ e: Option<&'a [u8]>,
+ ) -> Self {
+ TlsClientHelloContents {
+ version: TlsVersion(v),
+ rand_time: rt,
+ rand_data: rd,
+ session_id: sid,
+ ciphers: c,
+ comp: co,
+ ext: e,
+ }
+ }
+
+ pub fn get_version(&self) -> TlsVersion {
+ self.version
+ }
+
+ pub fn get_ciphers(&self) -> Vec<Option<&'static TlsCipherSuite>> {
+ self.ciphers.iter().map(|&x| x.get_ciphersuite()).collect()
+ }
+}
+
+impl<'a> ClientHello<'a> for TlsClientHelloContents<'a> {
+ fn version(&self) -> TlsVersion {
+ self.version
+ }
+
+ fn rand_data(&self) -> &'a [u8] {
+ self.rand_data
+ }
+
+ fn session_id(&self) -> Option<&'a [u8]> {
+ self.session_id
+ }
+
+ fn ciphers(&self) -> &Vec<TlsCipherSuiteID> {
+ &self.ciphers
+ }
+
+ fn comp(&self) -> &Vec<TlsCompressionID> {
+ &self.comp
+ }
+
+ fn ext(&self) -> Option<&'a [u8]> {
+ self.ext
+ }
+}
+
+/// TLS Server Hello (from TLS 1.0 to TLS 1.2)
+#[derive(Clone, PartialEq)]
+pub struct TlsServerHelloContents<'a> {
+ pub version: TlsVersion,
+ pub rand_time: u32,
+ pub rand_data: &'a [u8],
+ pub session_id: Option<&'a [u8]>,
+ pub cipher: TlsCipherSuiteID,
+ pub compression: TlsCompressionID,
+
+ pub ext: Option<&'a [u8]>,
+}
+
+/// TLS Server Hello (TLS 1.3 draft 18)
+#[derive(Clone, PartialEq)]
+pub struct TlsServerHelloV13Draft18Contents<'a> {
+ pub version: TlsVersion,
+ pub random: &'a [u8],
+ pub cipher: TlsCipherSuiteID,
+
+ pub ext: Option<&'a [u8]>,
+}
+
+/// TLS Hello Retry Request (TLS 1.3)
+#[derive(Clone, PartialEq)]
+pub struct TlsHelloRetryRequestContents<'a> {
+ pub version: TlsVersion,
+ pub cipher: TlsCipherSuiteID,
+
+ pub ext: Option<&'a [u8]>,
+}
+
+impl<'a> TlsServerHelloContents<'a> {
+ pub fn new(
+ v: u16,
+ rt: u32,
+ rd: &'a [u8],
+ sid: Option<&'a [u8]>,
+ c: u16,
+ co: u8,
+ e: Option<&'a [u8]>,
+ ) -> Self {
+ TlsServerHelloContents {
+ version: TlsVersion(v),
+ rand_time: rt,
+ rand_data: rd,
+ session_id: sid,
+ cipher: TlsCipherSuiteID(c),
+ compression: TlsCompressionID(co),
+ ext: e,
+ }
+ }
+
+ pub fn get_version(&self) -> TlsVersion {
+ self.version
+ }
+
+ pub fn get_cipher(&self) -> Option<&'static TlsCipherSuite> {
+ self.cipher.get_ciphersuite()
+ }
+}
+
+/// Session ticket, as defined in [RFC5077](https://tools.ietf.org/html/rfc5077)
+#[derive(Clone, Debug, PartialEq)]
+pub struct TlsNewSessionTicketContent<'a> {
+ pub ticket_lifetime_hint: u32,
+ pub ticket: &'a [u8],
+}
+
+/// A raw certificate, which should be a DER-encoded X.509 certificate.
+///
+/// See [RFC5280](https://tools.ietf.org/html/rfc5280) for X509v3 certificate format.
+#[derive(Clone, PartialEq)]
+pub struct RawCertificate<'a> {
+ pub data: &'a [u8],
+}
+
+/// The certificate chain, usually composed of the certificate, and all
+/// required certificate authorities.
+#[derive(Clone, Debug, PartialEq)]
+pub struct TlsCertificateContents<'a> {
+ pub cert_chain: Vec<RawCertificate<'a>>,
+}
+
+/// Certificate request, as defined in [RFC5246](https://tools.ietf.org/html/rfc5246) section 7.4.4
+///
+/// Note: TLS 1.2 adds SignatureAndHashAlgorithm (chapter 7.4.4) but do not declare it in A.4.2
+#[derive(Clone, Debug, PartialEq)]
+pub struct TlsCertificateRequestContents<'a> {
+ pub cert_types: Vec<u8>,
+ pub sig_hash_algs: Option<Vec<u16>>,
+ /// A list of DER-encoded distinguished names. See
+ /// [X.501](http://www.itu.int/rec/T-REC-X.501/en)
+ pub unparsed_ca: Vec<&'a [u8]>,
+}
+
+/// Server key exchange parameters
+///
+/// This is an opaque struct, since the content depends on the selected
+/// key exchange method.
+#[derive(Clone, PartialEq)]
+pub struct TlsServerKeyExchangeContents<'a> {
+ pub parameters: &'a [u8],
+}
+
+/// Client key exchange parameters
+///
+/// Content depends on the selected key exchange method.
+#[derive(Clone, PartialEq)]
+pub enum TlsClientKeyExchangeContents<'a> {
+ Dh(&'a [u8]),
+ Ecdh(ECPoint<'a>),
+ Unknown(&'a [u8]),
+}
+
+/// Certificate status response, as defined in [RFC6066](https://tools.ietf.org/html/rfc6066) section 8
+#[derive(Clone, Debug, PartialEq)]
+pub struct TlsCertificateStatusContents<'a> {
+ pub status_type: u8,
+ pub blob: &'a [u8],
+}
+
+/// Next protocol response, defined in
+/// [draft-agl-tls-nextprotoneg-03](https://tools.ietf.org/html/draft-agl-tls-nextprotoneg-03)
+#[derive(Clone, Debug, PartialEq)]
+pub struct TlsNextProtocolContent<'a> {
+ pub selected_protocol: &'a [u8],
+ pub padding: &'a [u8],
+}
+
+/// Key update request (TLS 1.3)
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub struct KeyUpdateRequest(pub u8);
+
+newtype_enum! {
+impl KeyUpdateRequest {
+ NotRequested = 0x0,
+ Requested = 0x1,
+}
+}
+
+/// Generic handshake message
+#[derive(Clone, Debug, PartialEq)]
+pub enum TlsMessageHandshake<'a> {
+ HelloRequest,
+ ClientHello(TlsClientHelloContents<'a>),
+ ServerHello(TlsServerHelloContents<'a>),
+ ServerHelloV13Draft18(TlsServerHelloV13Draft18Contents<'a>),
+ NewSessionTicket(TlsNewSessionTicketContent<'a>),
+ EndOfEarlyData,
+ HelloRetryRequest(TlsHelloRetryRequestContents<'a>),
+ Certificate(TlsCertificateContents<'a>),
+ ServerKeyExchange(TlsServerKeyExchangeContents<'a>),
+ CertificateRequest(TlsCertificateRequestContents<'a>),
+ ServerDone(&'a [u8]),
+ CertificateVerify(&'a [u8]),
+ ClientKeyExchange(TlsClientKeyExchangeContents<'a>),
+ Finished(&'a [u8]),
+ CertificateStatus(TlsCertificateStatusContents<'a>),
+ NextProtocol(TlsNextProtocolContent<'a>),
+ KeyUpdate(u8),
+}
+
+/// TLS application data
+///
+/// Since this message can only be sent after the handshake, data is
+/// stored as opaque.
+#[derive(Clone, Debug, PartialEq)]
+pub struct TlsMessageApplicationData<'a> {
+ pub blob: &'a [u8],
+}
+
+/// TLS heartbeat message, as defined in [RFC6520](https://tools.ietf.org/html/rfc6520)
+///
+/// Heartbeat messages should not be sent during handshake, but in practise
+/// they can (and this caused heartbleed).
+#[derive(Clone, Debug, PartialEq)]
+pub struct TlsMessageHeartbeat<'a> {
+ pub heartbeat_type: TlsHeartbeatMessageType,
+ pub payload_len: u16,
+ pub payload: &'a [u8],
+}
+
+/// TLS record header
+#[derive(Clone, Copy, PartialEq, NomBE)]
+pub struct TlsRecordHeader {
+ pub record_type: TlsRecordType,
+ pub version: TlsVersion,
+ pub len: u16,
+}
+
+/// TLS plaintext message
+///
+/// Plaintext records can only be found during the handshake.
+#[derive(Clone, Debug, PartialEq)]
+pub enum TlsMessage<'a> {
+ Handshake(TlsMessageHandshake<'a>),
+ ChangeCipherSpec,
+ Alert(TlsMessageAlert),
+ ApplicationData(TlsMessageApplicationData<'a>),
+ Heartbeat(TlsMessageHeartbeat<'a>),
+}
+
+/// TLS plaintext record
+///
+/// A TLS record can contain multiple messages (sharing the same record type).
+/// Plaintext records can only be found during the handshake.
+#[derive(Clone, Debug, PartialEq)]
+pub struct TlsPlaintext<'a> {
+ pub hdr: TlsRecordHeader,
+ pub msg: Vec<TlsMessage<'a>>,
+}
+
+/// TLS encrypted data
+///
+/// This struct only contains an opaque pointer (data are encrypted).
+#[derive(Clone, Debug, PartialEq)]
+pub struct TlsEncryptedContent<'a> {
+ pub blob: &'a [u8],
+}
+
+/// Encrypted TLS record (containing opaque data)
+#[derive(Clone, Debug, PartialEq)]
+pub struct TlsEncrypted<'a> {
+ pub hdr: TlsRecordHeader,
+ pub msg: TlsEncryptedContent<'a>,
+}
+
+/// Tls Record with raw (unparsed) data
+///
+/// Use `parse_tls_raw_record` to parse content
+#[derive(Clone, Debug, PartialEq)]
+pub struct TlsRawRecord<'a> {
+ pub hdr: TlsRecordHeader,
+ pub data: &'a [u8],
+}
+
+pub(crate) fn parse_cipher_suites(i: &[u8], len: usize) -> IResult<&[u8], Vec<TlsCipherSuiteID>> {
+ if len == 0 {
+ return Ok((i, Vec::new()));
+ }
+ if len % 2 == 1 || len > i.len() {
+ return Err(Err::Error(make_error(i, ErrorKind::LengthValue)));
+ }
+ let v = (&i[..len])
+ .chunks(2)
+ .map(|chunk| TlsCipherSuiteID((chunk[0] as u16) << 8 | chunk[1] as u16))
+ .collect();
+ Ok((&i[len..], v))
+}
+
+pub(crate) fn parse_compressions_algs(
+ i: &[u8],
+ len: usize,
+) -> IResult<&[u8], Vec<TlsCompressionID>> {
+ if len == 0 {
+ return Ok((i, Vec::new()));
+ }
+ if len > i.len() {
+ return Err(Err::Error(make_error(i, ErrorKind::LengthValue)));
+ }
+ let v = (&i[..len]).iter().map(|&it| TlsCompressionID(it)).collect();
+ Ok((&i[len..], v))
+}
+
+pub(crate) fn parse_tls_versions(i: &[u8]) -> IResult<&[u8], Vec<TlsVersion>> {
+ let len = i.len();
+ if len == 0 {
+ return Ok((i, Vec::new()));
+ }
+ if len % 2 == 1 || len > i.len() {
+ return Err(Err::Error(make_error(i, ErrorKind::LengthValue)));
+ }
+ let v = (&i[..len])
+ .chunks(2)
+ .map(|chunk| TlsVersion((chunk[0] as u16) << 8 | chunk[1] as u16))
+ .collect();
+ Ok((&i[len..], v))
+}
+
+fn parse_certs(i: &[u8]) -> IResult<&[u8], Vec<RawCertificate>> {
+ many0(complete(map(length_data(be_u24), |data| RawCertificate {
+ data,
+ })))(i)
+}
+
+/// Read TLS record header
+///
+/// This function is used to get the record header.
+/// After calling this function, caller can read the expected number of bytes and use
+/// `parse_tls_record_with_header` to parse content.
+#[inline]
+pub fn parse_tls_record_header(i: &[u8]) -> IResult<&[u8], TlsRecordHeader> {
+ TlsRecordHeader::parse(i)
+}
+
+#[allow(clippy::unnecessary_wraps)]
+fn parse_tls_handshake_msg_hello_request(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
+ Ok((i, TlsMessageHandshake::HelloRequest))
+}
+
+fn parse_tls_handshake_msg_client_hello(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
+ let (i, version) = be_u16(i)?;
+ let (i, rand_time) = be_u32(i)?;
+ let (i, rand_data) = take(28usize)(i)?; // 28 as 32 (aligned) - 4 (time)
+ let (i, sidlen) = verify(be_u8, |&n| n <= 32)(i)?;
+ let (i, sid) = cond(sidlen > 0, take(sidlen as usize))(i)?;
+ let (i, ciphers_len) = be_u16(i)?;
+ let (i, ciphers) = parse_cipher_suites(i, ciphers_len as usize)?;
+ let (i, comp_len) = be_u8(i)?;
+ let (i, comp) = parse_compressions_algs(i, comp_len as usize)?;
+ let (i, ext) = opt(complete(length_data(be_u16)))(i)?;
+ let content =
+ TlsClientHelloContents::new(version, rand_time, rand_data, sid, ciphers, comp, ext);
+ Ok((i, TlsMessageHandshake::ClientHello(content)))
+}
+
+fn parse_tls_handshake_msg_server_hello_tlsv12(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
+ map(
+ parse_tls_server_hello_tlsv12,
+ TlsMessageHandshake::ServerHello,
+ )(i)
+}
+
+pub(crate) fn parse_tls_server_hello_tlsv12(i: &[u8]) -> IResult<&[u8], TlsServerHelloContents> {
+ let (i, version) = be_u16(i)?;
+ let (i, rand_time) = be_u32(i)?;
+ let (i, rand_data) = take(28usize)(i)?; // 28 as 32 (aligned) - 4 (time)
+ let (i, sidlen) = verify(be_u8, |&n| n <= 32)(i)?;
+ let (i, sid) = cond(sidlen > 0, take(sidlen as usize))(i)?;
+ let (i, cipher) = be_u16(i)?;
+ let (i, comp) = be_u8(i)?;
+ let (i, ext) = opt(complete(length_data(be_u16)))(i)?;
+ let content =
+ TlsServerHelloContents::new(version, rand_time, rand_data, sid, cipher, comp, ext);
+ Ok((i, content))
+}
+
+fn parse_tls_handshake_msg_server_hello_tlsv13draft18(
+ i: &[u8],
+) -> IResult<&[u8], TlsMessageHandshake> {
+ let (i, version) = TlsVersion::parse(i)?;
+ let (i, random) = take(32usize)(i)?;
+ let (i, cipher) = map(be_u16, TlsCipherSuiteID)(i)?;
+ let (i, ext) = opt(complete(length_data(be_u16)))(i)?;
+ let content = TlsServerHelloV13Draft18Contents {
+ version,
+ random,
+ cipher,
+ ext,
+ };
+ Ok((i, TlsMessageHandshake::ServerHelloV13Draft18(content)))
+}
+
+fn parse_tls_handshake_msg_server_hello(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
+ let (_, version) = be_u16(i)?;
+ match version {
+ 0x7f12 => parse_tls_handshake_msg_server_hello_tlsv13draft18(i),
+ 0x0303 => parse_tls_handshake_msg_server_hello_tlsv12(i),
+ 0x0302 => parse_tls_handshake_msg_server_hello_tlsv12(i),
+ 0x0301 => parse_tls_handshake_msg_server_hello_tlsv12(i),
+ // 0x0300 => call!(parse_tls_handshake_msg_server_hello_sslv3(i),
+ _ => Err(Err::Error(make_error(i, ErrorKind::Tag))),
+ }
+}
+
+// RFC 5077 Stateless TLS Session Resumption
+fn parse_tls_handshake_msg_newsessionticket(
+ i: &[u8],
+ len: usize,
+) -> IResult<&[u8], TlsMessageHandshake> {
+ if len < 4 {
+ return Err(Err::Error(make_error(i, ErrorKind::Verify)));
+ }
+ let (i, ticket_lifetime_hint) = be_u32(i)?;
+ let (i, ticket) = take(len - 4)(i)?;
+ let content = TlsNewSessionTicketContent {
+ ticket_lifetime_hint,
+ ticket,
+ };
+ Ok((i, TlsMessageHandshake::NewSessionTicket(content)))
+}
+
+fn parse_tls_handshake_msg_hello_retry_request(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
+ let (i, version) = TlsVersion::parse(i)?;
+ let (i, cipher) = map(be_u16, TlsCipherSuiteID)(i)?;
+ let (i, ext) = opt(complete(length_data(be_u16)))(i)?;
+ let content = TlsHelloRetryRequestContents {
+ version,
+ cipher,
+ ext,
+ };
+ Ok((i, TlsMessageHandshake::HelloRetryRequest(content)))
+}
+
+pub(crate) fn parse_tls_certificate(i: &[u8]) -> IResult<&[u8], TlsCertificateContents> {
+ let (i, cert_len) = be_u24(i)?;
+ let (i, cert_chain) = map_parser(take(cert_len as usize), parse_certs)(i)?;
+ let content = TlsCertificateContents { cert_chain };
+ Ok((i, content))
+}
+
+fn parse_tls_handshake_msg_certificate(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
+ map(parse_tls_certificate, TlsMessageHandshake::Certificate)(i)
+}
+
+fn parse_tls_handshake_msg_serverkeyexchange(
+ i: &[u8],
+ len: usize,
+) -> IResult<&[u8], TlsMessageHandshake> {
+ map(take(len), |ext| {
+ TlsMessageHandshake::ServerKeyExchange(TlsServerKeyExchangeContents { parameters: ext })
+ })(i)
+}
+
+fn parse_tls_handshake_msg_serverdone(i: &[u8], len: usize) -> IResult<&[u8], TlsMessageHandshake> {
+ map(take(len), TlsMessageHandshake::ServerDone)(i)
+}
+
+fn parse_tls_handshake_msg_certificateverify(
+ i: &[u8],
+ len: usize,
+) -> IResult<&[u8], TlsMessageHandshake> {
+ map(take(len), TlsMessageHandshake::CertificateVerify)(i)
+}
+
+pub(crate) fn parse_tls_clientkeyexchange(
+ len: usize,
+) -> impl FnMut(&[u8]) -> IResult<&[u8], TlsClientKeyExchangeContents> {
+ move |i| map(take(len), TlsClientKeyExchangeContents::Unknown)(i)
+}
+
+fn parse_tls_handshake_msg_clientkeyexchange(
+ i: &[u8],
+ len: usize,
+) -> IResult<&[u8], TlsMessageHandshake> {
+ map(
+ parse_tls_clientkeyexchange(len),
+ TlsMessageHandshake::ClientKeyExchange,
+ )(i)
+}
+
+fn parse_certrequest_nosigalg(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
+ let (i, cert_types) = length_count(be_u8, be_u8)(i)?;
+ let (i, ca_len) = be_u16(i)?;
+ let (i, unparsed_ca) =
+ map_parser(take(ca_len as usize), many0(complete(length_data(be_u16))))(i)?;
+ let content = TlsCertificateRequestContents {
+ cert_types,
+ // sig_hash_algs: Some(sig_hash_algs),
+ sig_hash_algs: None,
+ unparsed_ca,
+ };
+ Ok((i, TlsMessageHandshake::CertificateRequest(content)))
+}
+
+fn parse_certrequest_full(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
+ let (i, cert_types) = length_count(be_u8, be_u8)(i)?;
+ let (i, sig_hash_algs_len) = be_u16(i)?;
+ let (i, sig_hash_algs) =
+ map_parser(take(sig_hash_algs_len as usize), many0(complete(be_u16)))(i)?;
+ let (i, ca_len) = be_u16(i)?;
+ let (i, unparsed_ca) =
+ map_parser(take(ca_len as usize), many0(complete(length_data(be_u16))))(i)?;
+ let content = TlsCertificateRequestContents {
+ cert_types,
+ sig_hash_algs: Some(sig_hash_algs),
+ unparsed_ca,
+ };
+ Ok((i, TlsMessageHandshake::CertificateRequest(content)))
+}
+
+#[inline]
+fn parse_tls_handshake_msg_certificaterequest(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
+ alt((
+ complete(parse_certrequest_full),
+ complete(parse_certrequest_nosigalg),
+ ))(i)
+}
+
+fn parse_tls_handshake_msg_finished(i: &[u8], len: usize) -> IResult<&[u8], TlsMessageHandshake> {
+ map(take(len), TlsMessageHandshake::Finished)(i)
+}
+
+// Defined in [RFC6066]
+// if status_type == 0, blob is a OCSPResponse, as defined in [RFC2560](https://tools.ietf.org/html/rfc2560)
+// Note that the OCSPResponse object is DER-encoded.
+fn parse_tls_handshake_msg_certificatestatus(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
+ let (i, status_type) = be_u8(i)?;
+ let (i, blob) = length_data(be_u24)(i)?;
+ let content = TlsCertificateStatusContents { status_type, blob };
+ Ok((i, TlsMessageHandshake::CertificateStatus(content)))
+}
+
+/// NextProtocol handshake message, as defined in
+/// [draft-agl-tls-nextprotoneg-03](https://tools.ietf.org/html/draft-agl-tls-nextprotoneg-03)
+/// Deprecated in favour of ALPN.
+fn parse_tls_handshake_msg_next_protocol(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
+ let (i, selected_protocol) = length_data(be_u8)(i)?;
+ let (i, padding) = length_data(be_u8)(i)?;
+ let next_proto = TlsNextProtocolContent {
+ selected_protocol,
+ padding,
+ };
+ Ok((i, TlsMessageHandshake::NextProtocol(next_proto)))
+}
+
+fn parse_tls_handshake_msg_key_update(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> {
+ map(be_u8, TlsMessageHandshake::KeyUpdate)(i)
+}
+
+/// Parse a TLS handshake message
+pub fn parse_tls_message_handshake(i: &[u8]) -> IResult<&[u8], TlsMessage> {
+ let (i, ht) = be_u8(i)?;
+ let (i, hl) = be_u24(i)?;
+ let (i, raw_msg) = take(hl)(i)?;
+ let (_, msg) = match TlsHandshakeType(ht) {
+ TlsHandshakeType::HelloRequest => parse_tls_handshake_msg_hello_request(raw_msg),
+ TlsHandshakeType::ClientHello => parse_tls_handshake_msg_client_hello(raw_msg),
+ TlsHandshakeType::ServerHello => parse_tls_handshake_msg_server_hello(raw_msg),
+ TlsHandshakeType::NewSessionTicket => {
+ parse_tls_handshake_msg_newsessionticket(raw_msg, hl as usize)
+ }
+ TlsHandshakeType::EndOfEarlyData => Ok((raw_msg, TlsMessageHandshake::EndOfEarlyData)),
+ TlsHandshakeType::HelloRetryRequest => parse_tls_handshake_msg_hello_retry_request(raw_msg),
+ TlsHandshakeType::Certificate => parse_tls_handshake_msg_certificate(raw_msg),
+ TlsHandshakeType::ServerKeyExchange => {
+ parse_tls_handshake_msg_serverkeyexchange(raw_msg, hl as usize)
+ }
+ TlsHandshakeType::CertificateRequest => parse_tls_handshake_msg_certificaterequest(raw_msg),
+ TlsHandshakeType::ServerDone => parse_tls_handshake_msg_serverdone(raw_msg, hl as usize),
+ TlsHandshakeType::CertificateVerify => {
+ parse_tls_handshake_msg_certificateverify(raw_msg, hl as usize)
+ }
+ TlsHandshakeType::ClientKeyExchange => {
+ parse_tls_handshake_msg_clientkeyexchange(raw_msg, hl as usize)
+ }
+ TlsHandshakeType::Finished => parse_tls_handshake_msg_finished(raw_msg, hl as usize),
+ // TlsHandshakeType::CertificateURL => parse_tls_handshake_msg_certificateurl(raw_msg),
+ TlsHandshakeType::CertificateStatus => parse_tls_handshake_msg_certificatestatus(raw_msg),
+ TlsHandshakeType::KeyUpdate => parse_tls_handshake_msg_key_update(raw_msg),
+ TlsHandshakeType::NextProtocol => parse_tls_handshake_msg_next_protocol(raw_msg),
+ _ => Err(Err::Error(make_error(i, ErrorKind::Switch))),
+ }?;
+ Ok((i, TlsMessage::Handshake(msg)))
+}
+
+/// Parse a TLS changecipherspec message
+// XXX add extra verification hdr.len == 1
+pub fn parse_tls_message_changecipherspec(i: &[u8]) -> IResult<&[u8], TlsMessage> {
+ let (i, _) = verify(be_u8, |&tag| tag == 0x01)(i)?;
+ Ok((i, TlsMessage::ChangeCipherSpec))
+}
+
+/// Parse a TLS alert message
+// XXX add extra verification hdr.len == 2
+pub fn parse_tls_message_alert(i: &[u8]) -> IResult<&[u8], TlsMessage> {
+ let (i, alert) = TlsMessageAlert::parse(i)?;
+ Ok((i, TlsMessage::Alert(alert)))
+}
+
+/// Parse a TLS applicationdata message
+///
+/// Read the entire input as applicationdata
+pub fn parse_tls_message_applicationdata(i: &[u8]) -> IResult<&[u8], TlsMessage> {
+ let msg = TlsMessage::ApplicationData(TlsMessageApplicationData { blob: i });
+ Ok((&[], msg))
+}
+
+/// Parse a TLS heartbeat message
+pub fn parse_tls_message_heartbeat(
+ i: &[u8],
+ tls_plaintext_len: u16,
+) -> IResult<&[u8], Vec<TlsMessage>> {
+ let (i, heartbeat_type) = TlsHeartbeatMessageType::parse(i)?;
+ let (i, payload_len) = be_u16(i)?;
+ if tls_plaintext_len < 3 {
+ return Err(Err::Error(make_error(i, ErrorKind::Verify)));
+ }
+ let (i, payload) = take(payload_len as usize)(i)?;
+ let v = vec![TlsMessage::Heartbeat(TlsMessageHeartbeat {
+ heartbeat_type,
+ payload_len,
+ payload,
+ })];
+ Ok((i, v))
+}
+
+/// Given data and a TLS record header, parse content.
+///
+/// A record can contain multiple messages (with the same type).
+///
+/// Note that message length is checked (not required for parser safety, but for
+/// strict protocol conformance).
+#[rustfmt::skip]
+#[allow(clippy::trivially_copy_pass_by_ref)] // TlsRecordHeader is only 6 bytes, but we prefer not breaking current API
+pub fn parse_tls_record_with_header<'i, 'hdr>(i:&'i [u8], hdr:&'hdr TlsRecordHeader ) -> IResult<&'i [u8], Vec<TlsMessage<'i>>> {
+ match hdr.record_type {
+ TlsRecordType::ChangeCipherSpec => many1(complete(parse_tls_message_changecipherspec))(i),
+ TlsRecordType::Alert => many1(complete(parse_tls_message_alert))(i),
+ TlsRecordType::Handshake => many1(complete(parse_tls_message_handshake))(i),
+ TlsRecordType::ApplicationData => many1(complete(parse_tls_message_applicationdata))(i),
+ TlsRecordType::Heartbeat => parse_tls_message_heartbeat(i, hdr.len),
+ _ => Err(Err::Error(make_error(i, ErrorKind::Switch)))
+ }
+}
+
+/// Parse one packet only, as plaintext
+/// A single record can contain multiple messages, they must share the same record type
+pub fn parse_tls_plaintext(i: &[u8]) -> IResult<&[u8], TlsPlaintext> {
+ let (i, hdr) = parse_tls_record_header(i)?;
+ if hdr.len > MAX_RECORD_LEN {
+ return Err(Err::Error(make_error(i, ErrorKind::TooLarge)));
+ }
+ let (i, msg) = map_parser(take(hdr.len as usize), |i| {
+ parse_tls_record_with_header(i, &hdr)
+ })(i)?;
+ Ok((i, TlsPlaintext { hdr, msg }))
+}
+
+/// Parse one packet only, as encrypted content
+pub fn parse_tls_encrypted(i: &[u8]) -> IResult<&[u8], TlsEncrypted> {
+ let (i, hdr) = parse_tls_record_header(i)?;
+ if hdr.len > MAX_RECORD_LEN {
+ return Err(Err::Error(make_error(i, ErrorKind::TooLarge)));
+ }
+ let (i, blob) = take(hdr.len as usize)(i)?;
+ let msg = TlsEncryptedContent { blob };
+ Ok((i, TlsEncrypted { hdr, msg }))
+}
+
+/// Read TLS record envelope, but do not decode data
+///
+/// This function is used to get the record type, and to make sure the record is
+/// complete (not fragmented).
+/// After calling this function, use `parse_tls_record_with_header` to parse content.
+pub fn parse_tls_raw_record(i: &[u8]) -> IResult<&[u8], TlsRawRecord> {
+ let (i, hdr) = parse_tls_record_header(i)?;
+ if hdr.len > MAX_RECORD_LEN {
+ return Err(Err::Error(make_error(i, ErrorKind::TooLarge)));
+ }
+ let (i, data) = take(hdr.len as usize)(i)?;
+ Ok((i, TlsRawRecord { hdr, data }))
+}
+
+/// Parse one packet only, as plaintext
+/// This function is deprecated. Use `parse_tls_plaintext` instead.
+///
+/// This function will be removed from API, as the name is not correct: it is
+/// not possible to parse TLS packets without knowing the TLS state.
+#[deprecated(since = "0.5.0", note = "Use parse_tls_plaintext")]
+#[inline]
+pub fn tls_parser(i: &[u8]) -> IResult<&[u8], TlsPlaintext> {
+ parse_tls_plaintext(i)
+}
+
+/// Parse one chunk of data, possibly containing multiple TLS plaintext records
+/// This function is deprecated. Use `parse_tls_plaintext` instead, checking if
+/// there are remaining bytes, and calling `parse_tls_plaintext` recursively.
+///
+/// This function will be removed from API, as it should be replaced by a more
+/// useful one to handle fragmentation.
+pub fn tls_parser_many(i: &[u8]) -> IResult<&[u8], Vec<TlsPlaintext>> {
+ many1(complete(parse_tls_plaintext))(i)
+}
diff --git a/rust/vendor/tls-parser/src/tls_alert.rs b/rust/vendor/tls-parser/src/tls_alert.rs
new file mode 100644
index 0000000..ec8e3ae
--- /dev/null
+++ b/rust/vendor/tls-parser/src/tls_alert.rs
@@ -0,0 +1,101 @@
+use nom_derive::*;
+use rusticata_macros::newtype_enum;
+
+/// TLS alert severity
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Nom)]
+pub struct TlsAlertSeverity(pub u8);
+
+newtype_enum! {
+impl display TlsAlertSeverity {
+ Warning = 0x01,
+ Fatal = 0x02
+}
+}
+
+/// TLS alert description
+///
+/// Alerts are defined in the [IANA TLS Alert
+/// Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-6)
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Nom)]
+pub struct TlsAlertDescription(pub u8);
+
+newtype_enum! {
+impl display TlsAlertDescription {
+ CloseNotify = 0x00,
+ UnexpectedMessage = 0x0A,
+ BadRecordMac = 0x14,
+ DecryptionFailed = 0x15,
+ RecordOverflow = 0x16,
+ DecompressionFailure = 0x1E,
+ HandshakeFailure = 0x28,
+ NoCertificate = 0x29,
+ BadCertificate = 0x2A,
+ UnsupportedCertificate = 0x2B,
+ CertificateRevoked = 0x2C,
+ CertificateExpired = 0x2D,
+ CertificateUnknown = 0x2E,
+ IllegalParameter = 0x2F,
+ UnknownCa = 0x30,
+ AccessDenied = 0x31,
+ DecodeError = 0x32,
+ DecryptError = 0x33,
+ ExportRestriction = 0x3C,
+ ProtocolVersion = 0x46,
+ InsufficientSecurity = 0x47,
+ InternalError = 0x50,
+ InappropriateFallback = 0x56,
+ UserCancelled = 0x5A,
+ NoRenegotiation = 0x64,
+ MissingExtension = 0x6d,
+ UnsupportedExtension = 0x6e,
+ CertUnobtainable = 0x6f,
+ UnrecognizedName = 0x70,
+ BadCertStatusResponse = 0x71,
+ BadCertHashValue = 0x72,
+ UnknownPskIdentity = 0x73,
+ CertificateRequired = 0x74,
+ NoApplicationProtocol = 0x78 // [RFC7301]
+}
+}
+
+/// TLS alert message
+#[derive(Clone, PartialEq, Nom)]
+pub struct TlsMessageAlert {
+ /// Should match a [TlsAlertSeverity](enum.TlsAlertSeverity.html) value
+ pub severity: TlsAlertSeverity,
+ /// Should match a [TlsAlertDescription](enum.TlsAlertDescription.html) value
+ pub code: TlsAlertDescription,
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tls_alert::*;
+
+ #[test]
+ fn test_tlsalert_cast_severity() {
+ let a = TlsAlertSeverity::Warning;
+
+ let a_u8 = a.0;
+ assert_eq!(a_u8, 0x01);
+
+ let b = TlsAlertSeverity(a_u8);
+ assert_eq!(b, TlsAlertSeverity::Warning);
+
+ let s = format!("{}", b);
+ assert_eq!(s, "Warning");
+
+ let s = format!("{}", TlsAlertSeverity(129));
+ assert_eq!(s, "TlsAlertSeverity(129 / 0x81)");
+ }
+
+ #[test]
+ fn test_tlsalert_cast_description() {
+ let a = TlsAlertDescription::HandshakeFailure;
+
+ let a_u8 = a.0;
+ assert_eq!(a_u8, 0x28);
+
+ let b = TlsAlertDescription(a_u8);
+ assert_eq!(b, TlsAlertDescription::HandshakeFailure);
+ }
+} // mod tests
diff --git a/rust/vendor/tls-parser/src/tls_ciphers.rs b/rust/vendor/tls-parser/src/tls_ciphers.rs
new file mode 100644
index 0000000..5603a7a
--- /dev/null
+++ b/rust/vendor/tls-parser/src/tls_ciphers.rs
@@ -0,0 +1,156 @@
+//!
+//! The [CIPHERS](static.CIPHERS.html) static hash map is built during the
+//! compilation of the crate, using `build.rs`. It parses a file derived from
+//! the [IANA TLS Cipher Suite
+//! Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4)
+//! to automatically extract parameters and add all known ciphersuites.
+
+#![allow(non_camel_case_types)]
+#![allow(clippy::unreadable_literal)]
+
+use enum_primitive::{enum_from_primitive, enum_from_primitive_impl, enum_from_primitive_impl_ty};
+
+enum_from_primitive! {
+/// Key exchange methods
+#[derive(Clone, Copy, Debug, PartialEq)]
+#[repr(u8)]
+pub enum TlsCipherKx {
+ Null = 0,
+ Psk,
+ Krb5,
+ Srp,
+ Rsa,
+ Dh,
+ Dhe,
+ Ecdh,
+ Ecdhe,
+ Aecdh,
+ Eccpwd,
+ Tls13,
+}
+}
+
+enum_from_primitive! {
+/// Authentication methods
+#[derive(Clone, Copy, Debug, PartialEq)]
+#[repr(u8)]
+pub enum TlsCipherAu {
+ Null = 0,
+ Psk,
+ Krb5,
+ Srp,
+ Srp_Dss,
+ Srp_Rsa,
+ Dss,
+ Rsa,
+ Dhe,
+ Ecdsa,
+ Eccpwd,
+ Tls13,
+}
+}
+
+enum_from_primitive! {
+/// Encryption methods
+#[derive(Clone, Copy, Debug, PartialEq)]
+#[repr(u8)]
+pub enum TlsCipherEnc {
+ Null,
+ Des,
+ TripleDes,
+ Rc2,
+ Rc4,
+ Aria,
+ Idea,
+ Seed,
+ Aes,
+ Camellia,
+ Chacha20_Poly1305,
+ Sm4,
+}
+}
+
+enum_from_primitive! {
+/// Encryption modes
+#[derive(Clone, Copy, Debug, PartialEq)]
+#[repr(u8)]
+pub enum TlsCipherEncMode {
+ Null,
+ Cbc,
+ Ccm,
+ Gcm,
+}
+}
+
+enum_from_primitive! {
+/// Message Authentication Code (MAC) methods
+#[derive(Clone, Copy, Debug, PartialEq)]
+#[repr(u8)]
+pub enum TlsCipherMac {
+ Null,
+ HmacMd5,
+ HmacSha1,
+ HmacSha256,
+ HmacSha384,
+ Aead,
+}
+}
+
+/// TLS Ciphersuite
+#[derive(Debug)]
+pub struct TlsCipherSuite {
+ pub name: &'static str,
+ pub id: u16,
+ pub kx: TlsCipherKx,
+ pub au: TlsCipherAu,
+ pub enc: TlsCipherEnc,
+ pub enc_mode: TlsCipherEncMode,
+ pub enc_size: u16,
+ pub mac: TlsCipherMac,
+ pub mac_size: u16,
+}
+
+include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
+
+impl TlsCipherSuite {
+ pub fn from_id(id: u16) -> Option<&'static TlsCipherSuite> {
+ CIPHERS.get(&id)
+ }
+
+ pub fn from_name<'a>(name: &'a str) -> Option<&'static TlsCipherSuite> {
+ CIPHERS.values().find(|&v| v.name == name)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tls_ciphers::{TlsCipherKx, TlsCipherSuite, CIPHERS};
+
+ #[test]
+ fn test_cipher_count() {
+ println!("loaded: {} cipher suites", CIPHERS.len());
+ assert!(!CIPHERS.is_empty());
+ }
+
+ #[test]
+ fn test_cipher_from_id() {
+ let cipher = TlsCipherSuite::from_id(0xc025).expect("could not get cipher");
+ println!("Found cipher: {:?}", cipher);
+ }
+
+ #[test]
+ fn test_cipher_from_name() {
+ let cipher = TlsCipherSuite::from_name("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384")
+ .expect("could not get cipher");
+ println!("Found cipher: {:?}", cipher);
+ }
+
+ #[test]
+ fn test_cipher_filter() {
+ let ecdhe_ciphers_count = CIPHERS
+ .values()
+ .filter(|c| c.kx == TlsCipherKx::Ecdhe)
+ .count();
+ assert!(ecdhe_ciphers_count > 20);
+ }
+}
diff --git a/rust/vendor/tls-parser/src/tls_debug.rs b/rust/vendor/tls-parser/src/tls_debug.rs
new file mode 100644
index 0000000..b449bfc
--- /dev/null
+++ b/rust/vendor/tls-parser/src/tls_debug.rs
@@ -0,0 +1,289 @@
+use crate::tls::*;
+use crate::tls_alert::*;
+use crate::tls_dh::*;
+use crate::tls_ec::*;
+use crate::tls_extensions::*;
+use crate::tls_sign_hash::*;
+use alloc::format;
+use alloc::vec::Vec;
+use core::fmt;
+use core::str::from_utf8;
+use rusticata_macros::debug::HexSlice;
+
+// ------------------------- tls.rs ------------------------------
+impl<'a> fmt::Debug for TlsClientHelloContents<'a> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("TlsClientHelloContents")
+ .field("version", &self.version)
+ .field("rand_time", &self.rand_time)
+ .field("rand_data", &HexSlice(self.rand_data))
+ .field("session_id", &self.session_id.map(HexSlice))
+ .field("ciphers", &self.ciphers)
+ .field("comp", &self.comp)
+ .field("ext", &self.ext.map(HexSlice))
+ .finish()
+ }
+}
+
+impl<'a> fmt::Debug for TlsServerHelloContents<'a> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("TlsServerHelloContents")
+ .field("version", &self.version)
+ .field("rand_time", &self.rand_time)
+ .field("rand_data", &HexSlice(self.rand_data))
+ .field("session_id", &self.session_id.map(HexSlice))
+ .field("cipher", &self.cipher)
+ .field("compression", &self.compression)
+ .field("ext", &self.ext.map(HexSlice))
+ .finish()
+ }
+}
+
+impl<'a> fmt::Debug for TlsServerHelloV13Draft18Contents<'a> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("TlsServerHelloV13Draft18Contents")
+ .field("version", &self.version)
+ .field("random", &HexSlice(self.random))
+ .field("cipher", &self.cipher)
+ .field("ext", &self.ext.map(HexSlice))
+ .finish()
+ }
+}
+
+impl<'a> fmt::Debug for TlsHelloRetryRequestContents<'a> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("TlsHelloRetryRequestContents")
+ .field("version", &self.version)
+ .field("ext", &self.ext.map(HexSlice))
+ .finish()
+ }
+}
+
+impl<'a> fmt::Debug for RawCertificate<'a> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("RawCertificate")
+ .field("data", &HexSlice(self.data))
+ .finish()
+ }
+}
+
+impl<'a> fmt::Debug for TlsServerKeyExchangeContents<'a> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("TlsServerKeyExchangeContents")
+ .field("parameters", &HexSlice(self.parameters))
+ .finish()
+ }
+}
+
+impl<'a> fmt::Debug for TlsClientKeyExchangeContents<'a> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ TlsClientKeyExchangeContents::Dh(p) => fmt.write_fmt(format_args!("{:?}", HexSlice(p))),
+ TlsClientKeyExchangeContents::Ecdh(ref p) => fmt.write_fmt(format_args!("{:?}", p)),
+ TlsClientKeyExchangeContents::Unknown(p) => {
+ fmt.write_fmt(format_args!("{:?}", HexSlice(p)))
+ }
+ }
+ }
+}
+
+impl fmt::Debug for TlsRecordHeader {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("TlsRecordHeader")
+ .field("type", &self.record_type)
+ .field("version", &self.version)
+ .field("len", &self.len)
+ .finish()
+ }
+}
+
+// ------------------------- tls_alert.rs ------------------------------
+impl fmt::Debug for TlsMessageAlert {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("TlsMessageAlert")
+ .field("severity", &self.severity)
+ .field("code", &self.code)
+ .finish()
+ }
+}
+
+// ------------------------- tls_dh.rs ------------------------------
+impl<'a> fmt::Debug for ServerDHParams<'a> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ let gs = self.dh_g.len() * 8;
+ fmt.debug_struct("ServerDHParams")
+ .field("group size", &gs)
+ .field("dh_p", &HexSlice(self.dh_p))
+ .field("dh_g", &HexSlice(self.dh_g))
+ .field("dh_ys", &HexSlice(self.dh_ys))
+ .finish()
+ }
+}
+
+// ------------------------- tls_ec.rs ------------------------------
+impl<'a> fmt::Debug for ECParametersContent<'a> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ ECParametersContent::ExplicitPrime(ref p) => {
+ fmt.write_fmt(format_args!("ExplicitPrime({:?})", p))
+ }
+ // ECParametersContent::ExplicitChar2(ref p) => {
+ // fmt.write_fmt(format_args!("ExplicitChar2({:?})", HexSlice(p)))
+ // }
+ ECParametersContent::NamedGroup(p) => write!(fmt, "{}", p),
+ }
+ }
+}
+
+impl<'a> fmt::Debug for ECParameters<'a> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("ECParameters")
+ .field("curve_type", &format!("{}", self.curve_type))
+ .field("params_content", &self.params_content)
+ .finish()
+ }
+}
+
+// ------------------------- tls_extensions.rs ------------------------------
+impl<'a> fmt::Debug for TlsExtension<'a> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ TlsExtension::SNI(ref v) => {
+ let v: Vec<_> = v
+ .iter()
+ .map(|&(ty, n)| {
+ let s = from_utf8(n).unwrap_or("<error decoding utf8 string>");
+ format!("type={},name={}", ty, s)
+ })
+ .collect();
+ write!(fmt, "TlsExtension::SNI({:?})", v)
+ }
+ TlsExtension::MaxFragmentLength(l) => {
+ write!(fmt, "TlsExtension::MaxFragmentLength({})", l)
+ }
+ TlsExtension::StatusRequest(data) => {
+ write!(fmt, "TlsExtension::StatusRequest({:?})", data)
+ }
+ TlsExtension::EllipticCurves(ref v) => {
+ let v2: Vec<_> = v.iter().map(|&curve| format!("{}", curve)).collect();
+ write!(fmt, "TlsExtension::EllipticCurves({:?})", v2)
+ }
+ TlsExtension::EcPointFormats(v) => write!(fmt, "TlsExtension::EcPointFormats({:?})", v),
+ TlsExtension::SignatureAlgorithms(ref v) => {
+ let v2: Vec<_> = v
+ .iter()
+ .map(|&alg| {
+ let s = format!("{}", SignatureScheme(alg));
+ if s.starts_with("SignatureScheme") {
+ format!(
+ "{}",
+ SignatureAndHashAlgorithm {
+ hash: HashAlgorithm((alg >> 8) as u8),
+ sign: SignAlgorithm((alg & 0xff) as u8)
+ }
+ )
+ } else {
+ s
+ }
+ })
+ .collect();
+ write!(fmt, "TlsExtension::SignatureAlgorithms({:?})", v2)
+ }
+ TlsExtension::SessionTicket(data) => {
+ write!(fmt, "TlsExtension::SessionTicket(data={:?})", data)
+ }
+ TlsExtension::RecordSizeLimit(data) => {
+ write!(fmt, "TlsExtension::RecordSizeLimit(data={})", data)
+ }
+ TlsExtension::KeyShareOld(data) => {
+ write!(fmt, "TlsExtension::KeyShareOld(data={:?})", HexSlice(data))
+ }
+ TlsExtension::KeyShare(data) => {
+ write!(fmt, "TlsExtension::KeyShare(data={:?})", HexSlice(data))
+ }
+ TlsExtension::PreSharedKey(data) => {
+ write!(fmt, "TlsExtension::PreSharedKey(data={:?})", HexSlice(data))
+ }
+ TlsExtension::EarlyData(o) => write!(fmt, "TlsExtension::EarlyData({:?})", o),
+ TlsExtension::SupportedVersions(ref v) => {
+ let v2: Vec<_> = v.iter().map(|c| format!("{}", c)).collect();
+ write!(fmt, "TlsExtension::SupportedVersions(v={:?})", v2)
+ }
+ TlsExtension::Cookie(data) => write!(fmt, "TlsExtension::Cookie(data={:?})", data),
+ TlsExtension::PskExchangeModes(ref v) => {
+ write!(fmt, "TlsExtension::PskExchangeModes({:?})", v)
+ }
+ TlsExtension::Heartbeat(mode) => write!(fmt, "TlsExtension::Heartbeat(mode={})", mode),
+ TlsExtension::ALPN(ref v) => {
+ let v: Vec<_> = v
+ .iter()
+ .map(|c| from_utf8(c).unwrap_or("<error decoding utf8 string>"))
+ .collect();
+ write!(fmt, "TlsExtension::ALPN({:?})", v)
+ }
+ TlsExtension::SignedCertificateTimestamp(data) => write!(
+ fmt,
+ "TlsExtension::SignedCertificateTimestamp(data={:?})",
+ data
+ ),
+ TlsExtension::Padding(data) => write!(fmt, "TlsExtension::Padding(data={:?})", data),
+ TlsExtension::EncryptThenMac => write!(fmt, "TlsExtension::EncryptThenMac"),
+ TlsExtension::ExtendedMasterSecret => write!(fmt, "TlsExtension::ExtendedMasterSecret"),
+ TlsExtension::OidFilters(ref v) => {
+ let v: Vec<_> = v.iter().map(|c| format!("{:?}", c)).collect();
+ write!(fmt, "TlsExtension::OidFilters({:?})", v)
+ }
+ TlsExtension::PostHandshakeAuth => write!(fmt, "TlsExtension::PostHandshakeAuth"),
+ TlsExtension::NextProtocolNegotiation => {
+ write!(fmt, "TlsExtension::NextProtocolNegotiation")
+ }
+ TlsExtension::RenegotiationInfo(data) => {
+ write!(fmt, "TlsExtension::RenegotiationInfo(data={:?})", data)
+ }
+ TlsExtension::EncryptedServerName {
+ ciphersuite, group, ..
+ } => write!(
+ fmt,
+ "TlsExtension::EncryptedServerName{{cipher: {:?}, group: {:?} ..}}",
+ ciphersuite, group
+ ),
+ TlsExtension::Grease(t, data) => write!(
+ fmt,
+ "TlsExtension::Grease(0x{:x},data={:?})",
+ t,
+ HexSlice(data)
+ ),
+ TlsExtension::Unknown(t, data) => write!(
+ fmt,
+ "TlsExtension::Unknown(type=0x{:x},data={:?})",
+ t.0, data
+ ),
+ }
+ }
+}
+
+// ------------------------- tls_sign_hash.rs ------------------------------
+impl fmt::Display for SignatureAndHashAlgorithm {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "HashSign({},{})", self.hash, self.sign)
+ }
+}
+
+impl fmt::Debug for SignatureAndHashAlgorithm {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(
+ fmt,
+ "SignatureAndHashAlgorithm({},{})",
+ self.hash, self.sign
+ )
+ }
+}
+
+impl<'a> fmt::Debug for DigitallySigned<'a> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("DigitallySigned")
+ .field("alg", &self.alg)
+ .field("data", &HexSlice(self.data))
+ .finish()
+ }
+}
diff --git a/rust/vendor/tls-parser/src/tls_dh.rs b/rust/vendor/tls-parser/src/tls_dh.rs
new file mode 100644
index 0000000..b0b6d89
--- /dev/null
+++ b/rust/vendor/tls-parser/src/tls_dh.rs
@@ -0,0 +1,23 @@
+use nom::multi::length_data;
+use nom::number::streaming::be_u16;
+use nom::IResult;
+use nom_derive::*;
+
+/// Diffie-Hellman parameters, defined in [RFC5246] section 7.4.3
+#[derive(PartialEq, NomBE)]
+pub struct ServerDHParams<'a> {
+ /// The prime modulus used for the Diffie-Hellman operation.
+ #[nom(Parse = "length_data(be_u16)")]
+ pub dh_p: &'a [u8],
+ /// The generator used for the Diffie-Hellman operation.
+ #[nom(Parse = "length_data(be_u16)")]
+ pub dh_g: &'a [u8],
+ /// The server's Diffie-Hellman public value (g^X mod p).
+ #[nom(Parse = "length_data(be_u16)")]
+ pub dh_ys: &'a [u8],
+}
+
+#[inline]
+pub fn parse_dh_params(i: &[u8]) -> IResult<&[u8], ServerDHParams> {
+ ServerDHParams::parse(i)
+}
diff --git a/rust/vendor/tls-parser/src/tls_ec.rs b/rust/vendor/tls-parser/src/tls_ec.rs
new file mode 100644
index 0000000..2130f86
--- /dev/null
+++ b/rust/vendor/tls-parser/src/tls_ec.rs
@@ -0,0 +1,200 @@
+use alloc::vec::Vec;
+use nom::error::{make_error, ErrorKind};
+use nom::multi::length_data;
+use nom::number::streaming::be_u8;
+use nom::{Err, IResult};
+use nom_derive::*;
+use rusticata_macros::newtype_enum;
+
+/// Named curves, as defined in [RFC4492](https://tools.ietf.org/html/rfc4492), [RFC7027](https://tools.ietf.org/html/rfc7027), [RFC7919](https://tools.ietf.org/html/rfc7919) and
+/// [IANA Supported Groups
+/// Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8)
+#[derive(Clone, Copy, PartialEq, Eq, NomBE)]
+pub struct NamedGroup(pub u16);
+
+newtype_enum! {
+impl debug NamedGroup {
+ Sect163k1 = 1,
+ Sect163r1 = 2,
+ Sect163r2 = 3,
+ Sect193r1 = 4,
+ Sect193r2 = 5,
+ Sect233k1 = 6,
+ Sect233r1 = 7,
+ Sect239k1 = 8,
+ Sect283k1 = 9,
+ Sect283r1 = 10,
+ Sect409k1 = 11,
+ Sect409r1 = 12,
+ Sect571k1 = 13,
+ Sect571r1 = 14,
+ Secp160k1 = 15,
+ Secp160r1 = 16,
+ Secp160r2 = 17,
+ Secp192k1 = 18,
+ Secp192r1 = 19,
+ Secp224k1 = 20,
+ Secp224r1 = 21,
+ Secp256k1 = 22,
+ Secp256r1 = 23,
+ Secp384r1 = 24,
+ Secp521r1 = 25,
+ BrainpoolP256r1 = 26,
+ BrainpoolP384r1 = 27,
+ BrainpoolP512r1 = 28,
+ EcdhX25519 = 29,
+ EcdhX448 = 30,
+ BrainpoolP256r1tls13 = 31,
+ BrainpoolP384r1tls13 = 32,
+ BrainpoolP512r1tls13 = 33,
+ Sm2 = 41,
+ Ffdhe2048 = 0x100,
+ Ffdhe3072 = 0x101,
+ Ffdhe4096 = 0x102,
+ Ffdhe6144 = 0x103,
+ Ffdhe8192 = 0x104,
+ ArbitraryExplicitPrimeCurves = 0xFF01,
+ ArbitraryExplicitChar2Curves = 0xFF02,
+}
+}
+
+impl NamedGroup {
+ /// Return key size of curve in bits, or None if unknown
+ pub fn key_bits(self: NamedGroup) -> Option<u16> {
+ match self {
+ NamedGroup::Sect163k1 => Some(163),
+ NamedGroup::Sect163r1 => Some(163),
+ NamedGroup::Sect163r2 => Some(163),
+ NamedGroup::Sect193r1 => Some(193),
+ NamedGroup::Sect193r2 => Some(193),
+ NamedGroup::Sect233k1 => Some(233),
+ NamedGroup::Sect233r1 => Some(233),
+ NamedGroup::Sect239k1 => Some(239),
+ NamedGroup::Sect283k1 => Some(283),
+ NamedGroup::Sect283r1 => Some(283),
+ NamedGroup::Sect409k1 => Some(409),
+ NamedGroup::Sect409r1 => Some(409),
+ NamedGroup::Sect571k1 => Some(571),
+ NamedGroup::Sect571r1 => Some(571),
+ NamedGroup::Secp160k1 => Some(160),
+ NamedGroup::Secp160r1 => Some(160),
+ NamedGroup::Secp160r2 => Some(160),
+ NamedGroup::Secp192k1 => Some(192),
+ NamedGroup::Secp192r1 => Some(192),
+ NamedGroup::Secp224k1 => Some(224),
+ NamedGroup::Secp224r1 => Some(224),
+ NamedGroup::Secp256k1 => Some(256),
+ NamedGroup::Secp256r1 => Some(256),
+ NamedGroup::Secp384r1 => Some(384),
+ NamedGroup::Secp521r1 => Some(521),
+ NamedGroup::BrainpoolP256r1 => Some(256),
+ NamedGroup::BrainpoolP384r1 => Some(384),
+ NamedGroup::BrainpoolP512r1 => Some(521),
+ NamedGroup::EcdhX25519 => Some(253),
+ _ => None,
+ }
+ }
+}
+
+/// Elliptic curve
+///
+/// a and b specify the coefficients of the curve
+#[derive(Debug, PartialEq, NomBE)]
+pub struct ECCurve<'a> {
+ #[nom(Parse = "length_data(be_u8)")]
+ pub a: &'a [u8],
+ #[nom(Parse = "length_data(be_u8)")]
+ pub b: &'a [u8],
+}
+
+/// Elliptic curve types, as defined in the
+/// [IANA EC Curve Type Registry
+/// Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-10)
+#[derive(Clone, Copy, PartialEq, Eq, NomBE)]
+pub struct ECCurveType(pub u8);
+
+newtype_enum! {
+impl display ECCurveType {
+ ExplicitPrime = 1,
+ ExplicitChar2 = 2,
+ NamedGroup = 3,
+}
+}
+
+/// EC Point
+#[derive(Clone, Debug, PartialEq, NomBE)]
+pub struct ECPoint<'a> {
+ #[nom(Parse = "length_data(be_u8)")]
+ pub point: &'a [u8],
+}
+
+/// Elliptic curve parameters, conveyed verbosely as a prime field, as
+/// defined in [RFC4492](https://tools.ietf.org/html/rfc4492) section 5.4
+#[derive(Debug, PartialEq, NomBE)]
+pub struct ExplicitPrimeContent<'a> {
+ #[nom(Parse = "length_data(be_u8)")]
+ pub prime_p: &'a [u8],
+ pub curve: ECCurve<'a>,
+ pub base: ECPoint<'a>,
+ #[nom(Parse = "length_data(be_u8)")]
+ pub order: &'a [u8],
+ #[nom(Parse = "length_data(be_u8)")]
+ pub cofactor: &'a [u8],
+}
+
+/// Elliptic curve parameters content (depending on EC type)
+#[derive(PartialEq, Nom)]
+#[nom(Selector = "ECCurveType")]
+pub enum ECParametersContent<'a> {
+ #[nom(Selector = "ECCurveType::ExplicitPrime")]
+ ExplicitPrime(ExplicitPrimeContent<'a>),
+ // TODO ExplicitChar2 is defined in [RFC4492] section 5.4
+ // #[nom(Selector="ECCurveType::ExplicitChar2")]
+ // ExplicitChar2(&'a [u8]),
+ #[nom(Selector = "ECCurveType::NamedGroup")]
+ NamedGroup(NamedGroup),
+}
+
+/// Elliptic curve parameters,
+/// defined in [RFC4492](https://tools.ietf.org/html/rfc4492) section 5.4
+#[derive(PartialEq, NomBE)]
+pub struct ECParameters<'a> {
+ /// Should match a [ECCurveType](enum.ECCurveType.html) value
+ pub curve_type: ECCurveType,
+ #[nom(Parse = "{|i| ECParametersContent::parse(i, curve_type)}")]
+ pub params_content: ECParametersContent<'a>,
+}
+
+/// ECDH parameters
+/// defined in [RFC4492](https://tools.ietf.org/html/rfc4492) section 5.4
+#[derive(Debug, PartialEq, NomBE)]
+pub struct ServerECDHParams<'a> {
+ pub curve_params: ECParameters<'a>,
+ pub public: ECPoint<'a>,
+}
+
+/// Parse the entire input as a list of named groups (curves)
+pub fn parse_named_groups(i: &[u8]) -> IResult<&[u8], Vec<NamedGroup>> {
+ let len = i.len();
+ if len == 0 {
+ return Ok((i, Vec::new()));
+ }
+ if len % 2 == 1 || len > i.len() {
+ return Err(Err::Error(make_error(i, ErrorKind::LengthValue)));
+ }
+ let v = (&i[..len])
+ .chunks(2)
+ .map(|chunk| NamedGroup((chunk[0] as u16) << 8 | chunk[1] as u16))
+ .collect();
+ Ok((&i[len..], v))
+}
+
+#[inline]
+pub fn parse_ec_parameters(i: &[u8]) -> IResult<&[u8], ECParameters> {
+ ECParameters::parse(i)
+}
+
+#[inline]
+pub fn parse_ecdh_params(i: &[u8]) -> IResult<&[u8], ServerECDHParams> {
+ ServerECDHParams::parse(i)
+}
diff --git a/rust/vendor/tls-parser/src/tls_extensions.rs b/rust/vendor/tls-parser/src/tls_extensions.rs
new file mode 100644
index 0000000..3c19aba
--- /dev/null
+++ b/rust/vendor/tls-parser/src/tls_extensions.rs
@@ -0,0 +1,747 @@
+//!
+//! TLS extensions are defined in:
+//!
+//! - [RFC4492](https://tools.ietf.org/html/rfc4492)
+//! - [RFC6066](https://tools.ietf.org/html/rfc6066)
+//! - [RFC7366](https://tools.ietf.org/html/rfc7366)
+//! - [RFC7627](https://tools.ietf.org/html/rfc7627)
+
+use crate::tls::{parse_tls_versions, TlsCipherSuiteID, TlsVersion};
+use crate::tls_ec::{parse_named_groups, NamedGroup};
+use alloc::{vec, vec::Vec};
+use core::convert::From;
+use nom::bytes::streaming::{tag, take};
+use nom::combinator::{complete, cond, map, map_parser, opt, verify};
+use nom::error::{make_error, ErrorKind};
+use nom::multi::{length_data, many0};
+use nom::number::streaming::{be_u16, be_u32, be_u8};
+use nom::{Err, IResult};
+use nom_derive::{NomBE, Parse};
+use rusticata_macros::newtype_enum;
+
+/// TLS extension types,
+/// defined in the [IANA Transport Layer Security (TLS)
+/// Extensions](http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml)
+/// registry
+#[derive(Clone, Copy, Debug, PartialEq, Eq, NomBE)]
+pub struct TlsExtensionType(pub u16);
+
+newtype_enum! {
+impl display TlsExtensionType {
+ ServerName = 0, // [RFC6066]
+ MaxFragmentLength = 1,
+ ClientCertificate = 2,
+ TrustedCaKeys = 3,
+ TruncatedHMac = 4,
+ StatusRequest = 5, // [RFC6066]
+ UserMapping = 6,
+ ClientAuthz = 7,
+ ServerAuthz = 8,
+ CertType = 9,
+ SupportedGroups = 10, // [RFC4492][RFC7919]
+ EcPointFormats = 11, // [RFC4492]
+ Srp = 12, // [RFC5054]
+ SignatureAlgorithms = 13, // [RFC8446]
+ UseSrtp = 14,
+ Heartbeat = 15, // [RFC6520]
+ ApplicationLayerProtocolNegotiation = 16, // [RFC7301]
+ StatusRequestv2 = 17,
+ SignedCertificateTimestamp = 18,
+ ClientCertificateType = 19,
+ ServerCertificateType = 20,
+ Padding = 21, // [RFC7685]
+ EncryptThenMac = 22, // [RFC7366]
+ ExtendedMasterSecret = 23, // [RFC7627]
+ TokenBinding = 24,
+ CachedInfo = 25,
+
+ RecordSizeLimit = 28, // [RFC8449]
+
+ SessionTicketTLS = 35,
+
+ KeyShareOld = 40, // moved to 51 in TLS 1.3 draft 23
+ PreSharedKey = 41, // [RFC8446]
+ EarlyData = 42, // [RFC8446]
+ SupportedVersions = 43, // [RFC8446]
+ Cookie = 44, // [RFC8446]
+ PskExchangeModes = 45, // [RFC8446]
+ TicketEarlyDataInfo = 46, // TLS 1.3 draft 18, removed in draft 19
+ CertificateAuthorities = 47,
+ OidFilters = 48, // [RFC8446]
+ PostHandshakeAuth = 49, // TLS 1.3 draft 20
+ SigAlgorithmsCert = 50, // TLS 1.3 draft 23
+ KeyShare = 51, // TLS 1.3 draft 23
+
+ NextProtocolNegotiation = 13172,
+
+ Grease = 0xfafa,
+
+ RenegotiationInfo = 0xff01, // [RFC5746]
+ EncryptedServerName = 0xffce, // draft-ietf-tls-esni
+}
+}
+
+impl TlsExtensionType {
+ pub fn from_u16(t: u16) -> TlsExtensionType {
+ TlsExtensionType(t)
+ }
+}
+
+impl From<TlsExtensionType> for u16 {
+ fn from(ext: TlsExtensionType) -> u16 {
+ ext.0
+ }
+}
+
+/// TLS extensions
+///
+#[derive(Clone, PartialEq)]
+pub enum TlsExtension<'a> {
+ SNI(Vec<(SNIType, &'a [u8])>),
+ MaxFragmentLength(u8),
+ StatusRequest(Option<(CertificateStatusType, &'a [u8])>),
+ EllipticCurves(Vec<NamedGroup>),
+ EcPointFormats(&'a [u8]),
+ SignatureAlgorithms(Vec<u16>),
+ RecordSizeLimit(u16),
+ SessionTicket(&'a [u8]),
+ KeyShareOld(&'a [u8]),
+ KeyShare(&'a [u8]),
+ PreSharedKey(&'a [u8]),
+ EarlyData(Option<u32>),
+ SupportedVersions(Vec<TlsVersion>),
+ Cookie(&'a [u8]),
+ PskExchangeModes(Vec<u8>),
+ Heartbeat(u8),
+ ALPN(Vec<&'a [u8]>),
+
+ SignedCertificateTimestamp(Option<&'a [u8]>),
+ Padding(&'a [u8]),
+ EncryptThenMac,
+ ExtendedMasterSecret,
+
+ OidFilters(Vec<OidFilter<'a>>),
+ PostHandshakeAuth,
+
+ NextProtocolNegotiation,
+
+ RenegotiationInfo(&'a [u8]),
+ EncryptedServerName {
+ ciphersuite: TlsCipherSuiteID,
+ group: NamedGroup,
+ key_share: &'a [u8],
+ record_digest: &'a [u8],
+ encrypted_sni: &'a [u8],
+ },
+
+ Grease(u16, &'a [u8]),
+
+ Unknown(TlsExtensionType, &'a [u8]),
+}
+
+impl<'a> From<&'a TlsExtension<'a>> for TlsExtensionType {
+ #[rustfmt::skip]
+ fn from(ext: &TlsExtension) -> TlsExtensionType {
+ match *ext {
+ TlsExtension::SNI(_) => TlsExtensionType::ServerName,
+ TlsExtension::MaxFragmentLength(_) => TlsExtensionType::MaxFragmentLength,
+ TlsExtension::StatusRequest(_) => TlsExtensionType::StatusRequest,
+ TlsExtension::EllipticCurves(_) => TlsExtensionType::SupportedGroups,
+ TlsExtension::EcPointFormats(_) => TlsExtensionType::EcPointFormats,
+ TlsExtension::SignatureAlgorithms(_) => TlsExtensionType::SignatureAlgorithms,
+ TlsExtension::SessionTicket(_) => TlsExtensionType::SessionTicketTLS,
+ TlsExtension::RecordSizeLimit(_) => TlsExtensionType::RecordSizeLimit,
+ TlsExtension::KeyShareOld(_) => TlsExtensionType::KeyShareOld,
+ TlsExtension::KeyShare(_) => TlsExtensionType::KeyShare,
+ TlsExtension::PreSharedKey(_) => TlsExtensionType::PreSharedKey,
+ TlsExtension::EarlyData(_) => TlsExtensionType::EarlyData,
+ TlsExtension::SupportedVersions(_) => TlsExtensionType::SupportedVersions,
+ TlsExtension::Cookie(_) => TlsExtensionType::Cookie,
+ TlsExtension::PskExchangeModes(_) => TlsExtensionType::PskExchangeModes,
+ TlsExtension::Heartbeat(_) => TlsExtensionType::Heartbeat,
+ TlsExtension::ALPN(_) => TlsExtensionType::ApplicationLayerProtocolNegotiation,
+ TlsExtension::SignedCertificateTimestamp(_) => TlsExtensionType::SignedCertificateTimestamp,
+ TlsExtension::Padding(_) => TlsExtensionType::Padding,
+ TlsExtension::EncryptThenMac => TlsExtensionType::EncryptThenMac,
+ TlsExtension::ExtendedMasterSecret => TlsExtensionType::ExtendedMasterSecret,
+ TlsExtension::OidFilters(_) => TlsExtensionType::OidFilters,
+ TlsExtension::PostHandshakeAuth => TlsExtensionType::PostHandshakeAuth,
+ TlsExtension::NextProtocolNegotiation => TlsExtensionType::NextProtocolNegotiation,
+ TlsExtension::RenegotiationInfo(_) => TlsExtensionType::RenegotiationInfo,
+ TlsExtension::EncryptedServerName{..} => TlsExtensionType::EncryptedServerName,
+ TlsExtension::Grease(_,_) => TlsExtensionType::Grease,
+ TlsExtension::Unknown(x,_) => x
+ }
+ }
+}
+
+#[derive(Clone, Debug, PartialEq)]
+pub struct KeyShareEntry<'a> {
+ pub group: NamedGroup, // NamedGroup
+ pub kx: &'a [u8], // Key Exchange Data
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, NomBE)]
+pub struct PskKeyExchangeMode(pub u8);
+
+newtype_enum! {
+impl PskKeyExchangeMode {
+ Psk = 0,
+ PskDhe = 1,
+}
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, NomBE)]
+pub struct SNIType(pub u8);
+
+newtype_enum! {
+impl display SNIType {
+ HostName = 0,
+}
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, NomBE)]
+pub struct CertificateStatusType(pub u8);
+
+newtype_enum! {
+impl debug CertificateStatusType {
+ OCSP = 1,
+}
+}
+
+#[derive(Clone, Debug, PartialEq)]
+pub struct OidFilter<'a> {
+ pub cert_ext_oid: &'a [u8],
+ pub cert_ext_val: &'a [u8],
+}
+
+// struct {
+// NameType name_type;
+// select (name_type) {
+// case host_name: HostName;
+// } name;
+// } ServerName;
+//
+// enum {
+// host_name(0), (255)
+// } NameType;
+//
+// opaque HostName<1..2^16-1>;
+pub fn parse_tls_extension_sni_hostname(i: &[u8]) -> IResult<&[u8], (SNIType, &[u8])> {
+ let (i, t) = SNIType::parse(i)?;
+ let (i, v) = length_data(be_u16)(i)?;
+ Ok((i, (t, v)))
+}
+
+// struct {
+// ServerName server_name_list<1..2^16-1>
+// } ServerNameList;
+pub fn parse_tls_extension_sni_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ if i.is_empty() {
+ // special case: SNI extension in server can be empty
+ return Ok((i, TlsExtension::SNI(Vec::new())));
+ }
+ let (i, list_len) = be_u16(i)?;
+ let (i, v) = map_parser(
+ take(list_len),
+ many0(complete(parse_tls_extension_sni_hostname)),
+ )(i)?;
+ Ok((i, TlsExtension::SNI(v)))
+}
+
+pub fn parse_tls_extension_sni(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 0x00])(i)?;
+ map_parser(length_data(be_u16), parse_tls_extension_sni_content)(i)
+}
+
+/// Max fragment length [RFC6066]
+pub fn parse_tls_extension_max_fragment_length_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ map(be_u8, TlsExtension::MaxFragmentLength)(i)
+}
+
+/// Max fragment length [RFC6066]
+pub fn parse_tls_extension_max_fragment_length(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 0x01])(i)?;
+ map_parser(
+ length_data(be_u16),
+ parse_tls_extension_max_fragment_length_content,
+ )(i)
+}
+
+/// Status Request [RFC6066]
+fn parse_tls_extension_status_request_content(
+ i: &[u8],
+ ext_len: u16,
+) -> IResult<&[u8], TlsExtension> {
+ match ext_len {
+ 0 => Ok((i, TlsExtension::StatusRequest(None))),
+ _ => {
+ let (i, status_type) = be_u8(i)?;
+ let (i, request) = take(ext_len - 1)(i)?;
+ Ok((
+ i,
+ TlsExtension::StatusRequest(Some((CertificateStatusType(status_type), request))),
+ ))
+ }
+ }
+}
+
+pub fn parse_tls_extension_status_request(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 0x05])(i)?;
+ let (i, ext_len) = be_u16(i)?;
+ map_parser(take(ext_len), move |d| {
+ parse_tls_extension_status_request_content(d, ext_len)
+ })(i)
+}
+
+// defined in rfc8422
+pub fn parse_tls_extension_elliptic_curves_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ map_parser(
+ length_data(be_u16),
+ map(parse_named_groups, TlsExtension::EllipticCurves),
+ )(i)
+}
+
+pub fn parse_tls_extension_elliptic_curves(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 0x0a])(i)?;
+ map_parser(
+ length_data(be_u16),
+ parse_tls_extension_elliptic_curves_content,
+ )(i)
+}
+
+pub fn parse_tls_extension_ec_point_formats_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ map(length_data(be_u8), TlsExtension::EcPointFormats)(i)
+}
+
+pub fn parse_tls_extension_ec_point_formats(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 0x0a])(i)?;
+ map_parser(
+ length_data(be_u16),
+ parse_tls_extension_ec_point_formats_content,
+ )(i)
+}
+
+/// Parse 'Signature Algorithms' extension (rfc8446, TLS 1.3 only)
+pub fn parse_tls_extension_signature_algorithms_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, l) = map_parser(length_data(be_u16), many0(complete(be_u16)))(i)?;
+ Ok((i, TlsExtension::SignatureAlgorithms(l))) // XXX SignatureAlgorithms or SignatureScheme
+}
+
+pub fn parse_tls_extension_signature_algorithms(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 13])(i)?;
+ map_parser(
+ length_data(be_u16),
+ parse_tls_extension_signature_algorithms_content,
+ )(i)
+}
+
+// rfc6520
+pub fn parse_tls_extension_heartbeat_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ map(be_u8, TlsExtension::Heartbeat)(i)
+}
+
+pub fn parse_tls_extension_heartbeat(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 0x0d])(i)?;
+ let (i, ext_len) = verify(be_u16, |&n| n == 1)(i)?;
+ map_parser(take(ext_len), parse_tls_extension_heartbeat_content)(i)
+}
+
+fn parse_protocol_name(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ length_data(be_u8)(i)
+}
+
+/// Defined in [RFC7301]
+pub fn parse_tls_extension_alpn_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, v) = map_parser(length_data(be_u16), many0(complete(parse_protocol_name)))(i)?;
+ Ok((i, TlsExtension::ALPN(v)))
+}
+
+/// Defined in [RFC7685]
+fn parse_tls_extension_padding_content(i: &[u8], ext_len: u16) -> IResult<&[u8], TlsExtension> {
+ map(take(ext_len), TlsExtension::Padding)(i)
+}
+
+/// Defined in [RFC6962]
+pub fn parse_tls_extension_signed_certificate_timestamp_content(
+ i: &[u8],
+) -> IResult<&[u8], TlsExtension> {
+ map(
+ opt(complete(length_data(be_u16))),
+ TlsExtension::SignedCertificateTimestamp,
+ )(i)
+}
+
+/// Encrypt-then-MAC is defined in [RFC7366]
+fn parse_tls_extension_encrypt_then_mac_content(
+ i: &[u8],
+ ext_len: u16,
+) -> IResult<&[u8], TlsExtension> {
+ if ext_len != 0 {
+ return Err(Err::Error(make_error(i, ErrorKind::Verify)));
+ }
+ Ok((i, TlsExtension::EncryptThenMac))
+}
+
+/// Encrypt-then-MAC is defined in [RFC7366]
+pub fn parse_tls_extension_encrypt_then_mac(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 0x16])(i)?;
+ let (i, ext_len) = be_u16(i)?;
+ map_parser(take(ext_len), move |d| {
+ parse_tls_extension_encrypt_then_mac_content(d, ext_len)
+ })(i)
+}
+
+/// Extended Master Secret is defined in [RFC7627]
+fn parse_tls_extension_extended_master_secret_content(
+ i: &[u8],
+ ext_len: u16,
+) -> IResult<&[u8], TlsExtension> {
+ if ext_len != 0 {
+ return Err(Err::Error(make_error(i, ErrorKind::Verify)));
+ }
+ Ok((i, TlsExtension::ExtendedMasterSecret))
+}
+
+/// Extended Master Secret is defined in [RFC7627]
+pub fn parse_tls_extension_extended_master_secret(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 0x17])(i)?;
+ let (i, ext_len) = be_u16(i)?;
+ map_parser(take(ext_len), move |d| {
+ parse_tls_extension_extended_master_secret_content(d, ext_len)
+ })(i)
+}
+
+/// Extended Record Size Limit is defined in [RFC7627]
+fn parse_tls_extension_record_size_limit(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ map(be_u16, TlsExtension::RecordSizeLimit)(i)
+}
+
+fn parse_tls_extension_session_ticket_content(
+ i: &[u8],
+ ext_len: u16,
+) -> IResult<&[u8], TlsExtension> {
+ map(take(ext_len), TlsExtension::SessionTicket)(i)
+}
+
+pub fn parse_tls_extension_session_ticket(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 0x23])(i)?;
+ let (i, ext_len) = be_u16(i)?;
+ map_parser(take(ext_len), move |d| {
+ parse_tls_extension_session_ticket_content(d, ext_len)
+ })(i)
+}
+
+fn parse_tls_extension_key_share_old_content(
+ i: &[u8],
+ ext_len: u16,
+) -> IResult<&[u8], TlsExtension> {
+ map(take(ext_len), TlsExtension::KeyShareOld)(i)
+}
+
+fn parse_tls_extension_key_share_content(i: &[u8], ext_len: u16) -> IResult<&[u8], TlsExtension> {
+ map(take(ext_len), TlsExtension::KeyShare)(i)
+}
+
+pub fn parse_tls_extension_key_share(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 0x33])(i)?;
+ let (i, ext_len) = be_u16(i)?;
+ map_parser(take(ext_len), move |d| {
+ parse_tls_extension_key_share_content(d, ext_len)
+ })(i)
+}
+
+fn parse_tls_extension_pre_shared_key_content(
+ i: &[u8],
+ ext_len: u16,
+) -> IResult<&[u8], TlsExtension> {
+ map(take(ext_len), TlsExtension::PreSharedKey)(i)
+}
+
+pub fn parse_tls_extension_pre_shared_key(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 0x28])(i)?;
+ let (i, ext_len) = be_u16(i)?;
+ map_parser(take(ext_len), move |d| {
+ parse_tls_extension_pre_shared_key_content(d, ext_len)
+ })(i)
+}
+
+fn parse_tls_extension_early_data_content(i: &[u8], ext_len: u16) -> IResult<&[u8], TlsExtension> {
+ map(cond(ext_len > 0, be_u32), TlsExtension::EarlyData)(i)
+}
+
+pub fn parse_tls_extension_early_data(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 0x2a])(i)?;
+ let (i, ext_len) = be_u16(i)?;
+ map_parser(take(ext_len), move |d| {
+ parse_tls_extension_early_data_content(d, ext_len)
+ })(i)
+}
+
+// TLS 1.3 draft 23
+// struct {
+// select (Handshake.msg_type) {
+// case client_hello:
+// ProtocolVersion versions<2..254>;
+//
+// case server_hello: /* and HelloRetryRequest */
+// ProtocolVersion selected_version;
+// };
+// } SupportedVersions;
+// XXX the content depends on the current message type
+// XXX first case has length 1 + 2*n, while the second case has length 2
+fn parse_tls_extension_supported_versions_content(
+ i: &[u8],
+ ext_len: u16,
+) -> IResult<&[u8], TlsExtension> {
+ if ext_len == 2 {
+ map(be_u16, |x| {
+ TlsExtension::SupportedVersions(vec![TlsVersion(x)])
+ })(i)
+ } else {
+ let (i, _) = be_u8(i)?;
+ if ext_len == 0 {
+ return Err(Err::Error(make_error(i, ErrorKind::Verify)));
+ }
+ let (i, l) = map_parser(take(ext_len - 1), parse_tls_versions)(i)?;
+ Ok((i, TlsExtension::SupportedVersions(l)))
+ }
+}
+
+pub fn parse_tls_extension_supported_versions(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 0x2b])(i)?;
+ let (i, ext_len) = be_u16(i)?;
+ map_parser(take(ext_len), move |d| {
+ parse_tls_extension_supported_versions_content(d, ext_len)
+ })(i)
+}
+
+fn parse_tls_extension_cookie_content(i: &[u8], ext_len: u16) -> IResult<&[u8], TlsExtension> {
+ map(take(ext_len), TlsExtension::Cookie)(i)
+}
+
+pub fn parse_tls_extension_cookie(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 0x2c])(i)?;
+ let (i, ext_len) = be_u16(i)?;
+ map_parser(take(ext_len), move |d| {
+ parse_tls_extension_cookie_content(d, ext_len)
+ })(i)
+}
+
+pub fn parse_tls_extension_psk_key_exchange_modes_content(
+ i: &[u8],
+) -> IResult<&[u8], TlsExtension> {
+ let (i, v) = length_data(be_u8)(i)?;
+ Ok((i, TlsExtension::PskExchangeModes(v.to_vec())))
+}
+
+pub fn parse_tls_extension_psk_key_exchange_modes(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, _) = tag([0x00, 0x2d])(i)?;
+ let (i, ext_len) = be_u16(i)?;
+ map_parser(
+ take(ext_len),
+ parse_tls_extension_psk_key_exchange_modes_content,
+ )(i)
+}
+
+/// Defined in RFC-draft-agl-tls-nextprotoneg-03. Deprecated in favour of ALPN.
+fn parse_tls_extension_npn_content(i: &[u8], ext_len: u16) -> IResult<&[u8], TlsExtension> {
+ if ext_len != 0 {
+ return Err(Err::Error(make_error(i, ErrorKind::Verify)));
+ }
+ Ok((i, TlsExtension::NextProtocolNegotiation))
+}
+
+/// Renegotiation Info, defined in [RFC5746]
+pub fn parse_tls_extension_renegotiation_info_content(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ map(length_data(be_u8), TlsExtension::RenegotiationInfo)(i)
+}
+
+/// Encrypted Server Name, defined in [draft-ietf-tls-esni]
+pub fn parse_tls_extension_encrypted_server_name(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, ciphersuite) = map(be_u16, TlsCipherSuiteID)(i)?;
+ let (i, group) = NamedGroup::parse(i)?;
+ let (i, key_share) = length_data(be_u16)(i)?;
+ let (i, record_digest) = length_data(be_u16)(i)?;
+ let (i, encrypted_sni) = length_data(be_u16)(i)?;
+ let esn = TlsExtension::EncryptedServerName {
+ ciphersuite,
+ group,
+ key_share,
+ record_digest,
+ encrypted_sni,
+ };
+ Ok((i, esn))
+}
+
+fn parse_tls_oid_filter(i: &[u8]) -> IResult<&[u8], OidFilter> {
+ let (i, cert_ext_oid) = length_data(be_u8)(i)?;
+ let (i, cert_ext_val) = length_data(be_u16)(i)?;
+ let filter = OidFilter {
+ cert_ext_oid,
+ cert_ext_val,
+ };
+ Ok((i, filter))
+}
+
+/// Defined in TLS 1.3 draft 19
+fn parse_tls_extension_oid_filters(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, v) = map_parser(length_data(be_u16), many0(complete(parse_tls_oid_filter)))(i)?;
+ Ok((i, TlsExtension::OidFilters(v)))
+}
+
+/// Defined in TLS 1.3 draft 20
+fn parse_tls_extension_post_handshake_auth_content(
+ i: &[u8],
+ ext_len: u16,
+) -> IResult<&[u8], TlsExtension> {
+ if ext_len != 0 {
+ return Err(Err::Error(make_error(i, ErrorKind::Verify)));
+ }
+ Ok((i, TlsExtension::PostHandshakeAuth))
+}
+
+pub fn parse_tls_extension_unknown(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, ext_type) = be_u16(i)?;
+ let (i, ext_data) = length_data(be_u16)(i)?;
+ Ok((
+ i,
+ TlsExtension::Unknown(TlsExtensionType(ext_type), ext_data),
+ ))
+}
+
+/// Parse a single TLS Client Hello extension
+pub fn parse_tls_client_hello_extension(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, ext_type) = be_u16(i)?;
+ let (i, ext_data) = length_data(be_u16)(i)?;
+ if ext_type & 0x0f0f == 0x0a0a {
+ return Ok((i, TlsExtension::Grease(ext_type, ext_data)));
+ }
+ let ext_len = ext_data.len() as u16;
+ let (_, ext) = match ext_type {
+ 0 => parse_tls_extension_sni_content(ext_data),
+ 1 => parse_tls_extension_max_fragment_length_content(ext_data),
+ 5 => parse_tls_extension_status_request_content(ext_data, ext_len),
+ 10 => parse_tls_extension_elliptic_curves_content(ext_data),
+ 11 => parse_tls_extension_ec_point_formats_content(ext_data),
+ 13 => parse_tls_extension_signature_algorithms_content(ext_data),
+ 15 => parse_tls_extension_heartbeat_content(ext_data),
+ 16 => parse_tls_extension_alpn_content(ext_data),
+ 18 => parse_tls_extension_signed_certificate_timestamp_content(ext_data), // ok XXX should be empty
+ 21 => parse_tls_extension_padding_content(ext_data, ext_len),
+ 22 => parse_tls_extension_encrypt_then_mac_content(ext_data, ext_len),
+ 23 => parse_tls_extension_extended_master_secret_content(ext_data, ext_len),
+ 28 => parse_tls_extension_record_size_limit(ext_data),
+ 35 => parse_tls_extension_session_ticket_content(ext_data, ext_len),
+ 41 => parse_tls_extension_pre_shared_key_content(ext_data, ext_len),
+ 42 => parse_tls_extension_early_data_content(ext_data, ext_len),
+ 43 => parse_tls_extension_supported_versions_content(ext_data, ext_len),
+ 44 => parse_tls_extension_cookie_content(ext_data, ext_len),
+ 45 => parse_tls_extension_psk_key_exchange_modes_content(ext_data),
+ 48 => parse_tls_extension_oid_filters(ext_data),
+ 49 => parse_tls_extension_post_handshake_auth_content(ext_data, ext_len),
+ 51 => parse_tls_extension_key_share_content(ext_data, ext_len), // XXX request
+ 13172 => parse_tls_extension_npn_content(ext_data, ext_len), // XXX must be empty
+ 0xff01 => parse_tls_extension_renegotiation_info_content(ext_data),
+ 0xffce => parse_tls_extension_encrypted_server_name(ext_data),
+ _ => Ok((
+ i,
+ TlsExtension::Unknown(TlsExtensionType(ext_type), ext_data),
+ )),
+ }?;
+ Ok((i, ext))
+}
+
+/// Parse a single TLS Server Hello extension
+pub fn parse_tls_server_hello_extension(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, ext_type) = be_u16(i)?;
+ let (i, ext_data) = length_data(be_u16)(i)?;
+ if ext_type & 0x0f0f == 0x0a0a {
+ return Ok((i, TlsExtension::Grease(ext_type, ext_data)));
+ }
+ let ext_len = ext_data.len() as u16;
+ let (_, ext) = match ext_type {
+ 0 => parse_tls_extension_sni_content(ext_data), // XXX SHALL be empty (RFC6066 section 3)
+ 1 => parse_tls_extension_max_fragment_length_content(ext_data),
+ 5 => parse_tls_extension_status_request_content(ext_data, ext_len), // SHALL be empty
+ 11 => parse_tls_extension_ec_point_formats_content(ext_data), // ok XXX only one
+ 13 => parse_tls_extension_signature_algorithms_content(ext_data), // XXX allowed?
+ 15 => parse_tls_extension_heartbeat_content(ext_data),
+ 16 => parse_tls_extension_alpn_content(ext_data), // ok XXX MUST contain one protocol name
+ 18 => parse_tls_extension_signed_certificate_timestamp_content(ext_data),
+ 21 => parse_tls_extension_encrypt_then_mac_content(ext_data, ext_len),
+ 23 => parse_tls_extension_extended_master_secret_content(ext_data, ext_len),
+ 28 => parse_tls_extension_record_size_limit(ext_data),
+ 35 => parse_tls_extension_session_ticket_content(ext_data, ext_len),
+ 41 => parse_tls_extension_pre_shared_key_content(ext_data, ext_len),
+ 42 => parse_tls_extension_early_data_content(ext_data, ext_len),
+ 43 => parse_tls_extension_supported_versions_content(ext_data, ext_len), // ok XXX only one
+ 44 => parse_tls_extension_cookie_content(ext_data, ext_len),
+ 51 => parse_tls_extension_key_share_content(ext_data, ext_len), // XXX selected entry
+ 13172 => parse_tls_extension_npn_content(ext_data, ext_len),
+ 0xff01 => parse_tls_extension_renegotiation_info_content(ext_data),
+ _ => Ok((
+ i,
+ TlsExtension::Unknown(TlsExtensionType(ext_type), ext_data),
+ )),
+ }?;
+ Ok((i, ext))
+}
+
+/// Parse a single TLS extension (of any type)
+pub fn parse_tls_extension(i: &[u8]) -> IResult<&[u8], TlsExtension> {
+ let (i, ext_type) = be_u16(i)?;
+ let (i, ext_data) = length_data(be_u16)(i)?;
+ if ext_type & 0x0f0f == 0x0a0a {
+ return Ok((i, TlsExtension::Grease(ext_type, ext_data)));
+ }
+ let ext_len = ext_data.len() as u16;
+ let (_, ext) = match ext_type {
+ 0 => parse_tls_extension_sni_content(ext_data),
+ 1 => parse_tls_extension_max_fragment_length_content(ext_data),
+ 5 => parse_tls_extension_status_request_content(ext_data, ext_len),
+ 10 => parse_tls_extension_elliptic_curves_content(ext_data),
+ 11 => parse_tls_extension_ec_point_formats_content(ext_data),
+ 13 => parse_tls_extension_signature_algorithms_content(ext_data),
+ 15 => parse_tls_extension_heartbeat_content(ext_data),
+ 16 => parse_tls_extension_alpn_content(ext_data),
+ 18 => parse_tls_extension_signed_certificate_timestamp_content(ext_data),
+ 21 => parse_tls_extension_padding_content(ext_data, ext_len),
+ 22 => parse_tls_extension_encrypt_then_mac_content(ext_data, ext_len),
+ 23 => parse_tls_extension_extended_master_secret_content(ext_data, ext_len),
+ 28 => parse_tls_extension_record_size_limit(ext_data),
+ 35 => parse_tls_extension_session_ticket_content(ext_data, ext_len),
+ 40 => parse_tls_extension_key_share_old_content(ext_data, ext_len),
+ 41 => parse_tls_extension_pre_shared_key_content(ext_data, ext_len),
+ 42 => parse_tls_extension_early_data_content(ext_data, ext_len),
+ 43 => parse_tls_extension_supported_versions_content(ext_data, ext_len),
+ 44 => parse_tls_extension_cookie_content(ext_data, ext_len),
+ 45 => parse_tls_extension_psk_key_exchange_modes_content(ext_data),
+ 48 => parse_tls_extension_oid_filters(ext_data),
+ 49 => parse_tls_extension_post_handshake_auth_content(ext_data, ext_len),
+ 51 => parse_tls_extension_key_share_content(ext_data, ext_len),
+ 13172 => parse_tls_extension_npn_content(ext_data, ext_len),
+ 0xff01 => parse_tls_extension_renegotiation_info_content(ext_data),
+ 0xffce => parse_tls_extension_encrypted_server_name(ext_data),
+ _ => Ok((
+ i,
+ TlsExtension::Unknown(TlsExtensionType(ext_type), ext_data),
+ )),
+ }?;
+ Ok((i, ext))
+}
+
+/// Parse zero or more TLS Client Hello extensions
+pub fn parse_tls_client_hello_extensions(i: &[u8]) -> IResult<&[u8], Vec<TlsExtension>> {
+ many0(complete(parse_tls_client_hello_extension))(i)
+}
+
+/// Parse zero or more TLS Server Hello extensions
+pub fn parse_tls_server_hello_extensions(i: &[u8]) -> IResult<&[u8], Vec<TlsExtension>> {
+ many0(complete(parse_tls_server_hello_extension))(i)
+}
+
+/// Parse zero or more TLS extensions (of any type)
+pub fn parse_tls_extensions(i: &[u8]) -> IResult<&[u8], Vec<TlsExtension>> {
+ many0(complete(parse_tls_extension))(i)
+}
diff --git a/rust/vendor/tls-parser/src/tls_serialize.rs b/rust/vendor/tls-parser/src/tls_serialize.rs
new file mode 100644
index 0000000..d6d99b6
--- /dev/null
+++ b/rust/vendor/tls-parser/src/tls_serialize.rs
@@ -0,0 +1,568 @@
+use crate::tls::*;
+use crate::tls_ec::{ECPoint, NamedGroup};
+use crate::tls_extensions::{SNIType, TlsExtension, TlsExtensionType};
+use alloc::vec::Vec;
+use cookie_factory::bytes::{be_u16, be_u24, be_u32, be_u8};
+use cookie_factory::combinator::slice;
+use cookie_factory::multi::{all, many_ref};
+use cookie_factory::sequence::tuple;
+use cookie_factory::*;
+use std::io::Write;
+
+pub use cookie_factory::GenError;
+pub use rusticata_macros::Serialize;
+
+fn gen_tls_ext_sni_hostname<'a, 'b: 'a, W: Write + 'a>(
+ i: &(SNIType, &'b [u8]),
+) -> impl SerializeFn<W> + 'a {
+ tuple((be_u8((i.0).0 as u8), be_u16(i.1.len() as u16), slice(i.1)))
+}
+
+fn length_be_u16<W, F>(f: F) -> impl SerializeFn<W>
+where
+ W: Write,
+ F: SerializeFn<Vec<u8>>,
+{
+ move |out| {
+ // use a temporary buffer
+ let (buf, len) = gen(&f, Vec::new())?;
+ tuple((be_u16(len as u16), slice(buf)))(out)
+ }
+}
+
+fn length_be_u24<W, F>(f: F) -> impl SerializeFn<W>
+where
+ W: Write,
+ F: SerializeFn<Vec<u8>>,
+{
+ move |out| {
+ // use a temporary buffer
+ let (buf, len) = gen(&f, Vec::new())?;
+ tuple((be_u24(len as u32), slice(buf)))(out)
+ }
+}
+
+fn tagged_extension<W, F>(tag: u16, f: F) -> impl SerializeFn<W>
+where
+ W: Write,
+ F: SerializeFn<Vec<u8>>,
+{
+ move |out| tuple((be_u16(tag), length_be_u16(&f)))(out)
+}
+
+fn gen_tls_ext_sni<'a, W>(m: &'a [(SNIType, &[u8])]) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ tagged_extension(
+ u16::from(TlsExtensionType::ServerName),
+ length_be_u16(many_ref(m, gen_tls_ext_sni_hostname)),
+ )
+}
+
+fn gen_tls_ext_max_fragment_length<W>(l: u8) -> impl SerializeFn<W>
+where
+ W: Write,
+{
+ tagged_extension(u16::from(TlsExtensionType::MaxFragmentLength), be_u8(l))
+}
+
+fn gen_tls_named_group<W>(g: NamedGroup) -> impl SerializeFn<W>
+where
+ W: Write,
+{
+ be_u16(g.0)
+}
+
+fn gen_tls_ext_elliptic_curves<'a, W>(v: &'a [NamedGroup]) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ tagged_extension(
+ u16::from(TlsExtensionType::SupportedGroups),
+ length_be_u16(all(v.iter().map(|&g| gen_tls_named_group(g)))),
+ )
+}
+
+/// Serialize a single TLS extension
+///
+/// # Example
+///
+/// ```rust
+/// use cookie_factory::{gen_simple, GenError};
+/// use tls_parser::TlsExtension;
+/// use tls_parser::gen_tls_extensions;
+///
+/// fn extensions_to_vec(ext: &[TlsExtension]) -> Result<Vec<u8>, GenError> {
+/// gen_simple(gen_tls_extensions(&ext), Vec::new())
+/// }
+/// ```
+///
+/// # Note
+///
+/// **Implementation is incomplete:
+/// only a few extensions are supported** (*Work in progress*)
+pub fn gen_tls_extension<'a, W>(m: &'a TlsExtension) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ move |out| match m {
+ TlsExtension::SNI(ref v) => gen_tls_ext_sni(v)(out),
+ TlsExtension::MaxFragmentLength(l) => gen_tls_ext_max_fragment_length(*l)(out),
+
+ TlsExtension::EllipticCurves(ref v) => gen_tls_ext_elliptic_curves(v)(out),
+ _ => Err(GenError::NotYetImplemented),
+ }
+}
+
+/// Serialize a list of TLS extensions
+pub fn gen_tls_extensions<'a, W>(m: &'a [TlsExtension]) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ length_be_u16(many_ref(m, gen_tls_extension))
+}
+
+fn gen_tls_sessionid<'a, W>(m: &'a Option<&[u8]>) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ move |out| match m {
+ None => be_u8(0)(out),
+ Some(o) => be_u8(o.len() as u8)(out).and_then(slice(o)),
+ }
+}
+
+fn maybe_extensions<'a, W>(m: &'a Option<&[u8]>) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ move |out| match m {
+ Some(o) => be_u16(o.len() as u16)(out).and_then(slice(o)),
+ None => be_u16(0)(out),
+ }
+}
+
+/// Serialize a ClientHello message
+pub fn gen_tls_clienthello<'a, W>(m: &'a TlsClientHelloContents) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ tuple((
+ be_u8(u8::from(TlsHandshakeType::ClientHello)),
+ length_be_u24(tuple((
+ be_u16(m.version.0),
+ be_u32(m.rand_time),
+ slice(m.rand_data), // check that length is 28
+ gen_tls_sessionid(&m.session_id),
+ be_u16(m.ciphers.len() as u16 * 2),
+ all(m.ciphers.iter().map(|cipher| be_u16(cipher.0))),
+ be_u8(m.comp.len() as u8),
+ all(m.comp.iter().map(|comp| be_u8(comp.0))),
+ maybe_extensions(&m.ext),
+ ))),
+ ))
+}
+
+/// Serialize a ServerHello message
+pub fn gen_tls_serverhello<'a, W>(m: &'a TlsServerHelloContents) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ tuple((
+ be_u8(u8::from(TlsHandshakeType::ServerHello)),
+ length_be_u24(tuple((
+ be_u16(m.version.0),
+ be_u32(m.rand_time),
+ slice(m.rand_data), // check that length is 28
+ gen_tls_sessionid(&m.session_id),
+ be_u16(m.cipher.0),
+ be_u8(m.compression.0),
+ maybe_extensions(&m.ext),
+ ))),
+ ))
+}
+
+/// Serialize a ServerHello (TLS 1.3 draft 18) message
+pub fn gen_tls_serverhellodraft18<'a, W>(
+ m: &'a TlsServerHelloV13Draft18Contents,
+) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ tuple((
+ be_u8(u8::from(TlsHandshakeType::ServerHello)),
+ length_be_u24(tuple((
+ be_u16(m.version.0),
+ slice(m.random), // check that length is 32
+ be_u16(m.cipher.0),
+ maybe_extensions(&m.ext),
+ ))),
+ ))
+}
+
+/// Serialize a ClientKeyExchange message, from raw contents
+fn gen_tls_clientkeyexchange_unknown<'a, W>(m: &'a [u8]) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ tuple((
+ be_u8(u8::from(TlsHandshakeType::ClientKeyExchange)),
+ length_be_u24(slice(m)),
+ ))
+}
+
+/// Serialize a ClientKeyExchange message, for DH parameters
+fn gen_tls_clientkeyexchange_dh<'a, W>(m: &'a [u8]) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ tuple((
+ be_u8(u8::from(TlsHandshakeType::ClientKeyExchange)),
+ length_be_u24(length_be_u16(slice(m))),
+ ))
+}
+
+/// Serialize a ClientKeyExchange message, for ECDH parameters
+fn gen_tls_clientkeyexchange_ecdh<'a, W>(m: &'a ECPoint) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ tuple((
+ be_u8(u8::from(TlsHandshakeType::ClientKeyExchange)),
+ length_be_u24(tuple((
+ // for ECDH, length is only 1 byte
+ be_u8(m.point.len() as u8),
+ slice(m.point),
+ ))),
+ ))
+}
+
+/// Serialize a ClientKeyExchange message
+pub fn gen_tls_clientkeyexchange<'a, W>(
+ m: &'a TlsClientKeyExchangeContents,
+) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ move |out| match m {
+ TlsClientKeyExchangeContents::Unknown(b) => gen_tls_clientkeyexchange_unknown(b)(out),
+ TlsClientKeyExchangeContents::Dh(b) => gen_tls_clientkeyexchange_dh(b)(out),
+ TlsClientKeyExchangeContents::Ecdh(ref b) => gen_tls_clientkeyexchange_ecdh(b)(out),
+ }
+}
+
+/// Serialize a HelloRequest message
+pub fn gen_tls_hellorequest<W>() -> impl SerializeFn<W>
+where
+ W: Write,
+{
+ tuple((be_u8(u8::from(TlsHandshakeType::HelloRequest)), be_u24(0)))
+}
+
+/// Serialize a Finished message
+pub fn gen_tls_finished<'a, W>(m: &'a [u8]) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ tuple((
+ be_u8(u8::from(TlsHandshakeType::Finished)),
+ length_be_u24(slice(m)),
+ ))
+}
+
+/// Serialize a TLS handshake message
+fn gen_tls_messagehandshake<'a, W>(m: &'a TlsMessageHandshake<'a>) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ move |out| match m {
+ TlsMessageHandshake::HelloRequest => gen_tls_hellorequest()(out),
+ TlsMessageHandshake::ClientHello(ref m) => gen_tls_clienthello(m)(out),
+ TlsMessageHandshake::ServerHello(ref m) => gen_tls_serverhello(m)(out),
+ TlsMessageHandshake::ServerHelloV13Draft18(ref m) => gen_tls_serverhellodraft18(m)(out),
+ TlsMessageHandshake::ClientKeyExchange(ref m) => gen_tls_clientkeyexchange(m)(out),
+ TlsMessageHandshake::Finished(m) => gen_tls_finished(m)(out),
+ _ => Err(GenError::NotYetImplemented),
+ }
+}
+
+impl<'a> Serialize<Vec<u8>> for TlsMessageHandshake<'a> {
+ type Error = GenError;
+ fn serialize(&self) -> Result<Vec<u8>, Self::Error> {
+ gen_simple(gen_tls_messagehandshake(self), Vec::new())
+ }
+}
+
+/// Serialize a ChangeCipherSpec message
+pub fn gen_tls_changecipherspec<W>() -> impl SerializeFn<W>
+where
+ W: Write,
+{
+ be_u8(u8::from(TlsRecordType::ChangeCipherSpec))
+}
+
+/// Serialize a TLS message
+///
+/// # Example
+///
+/// ```rust
+/// use cookie_factory::{gen_simple, GenError};
+/// use tls_parser::TlsMessage;
+/// use tls_parser::gen_tls_message;
+///
+/// fn tls_message_to_vec(msg: &TlsMessage) -> Result<Vec<u8>, GenError> {
+/// gen_simple(gen_tls_message(&msg), Vec::new())
+/// }
+/// ```
+pub fn gen_tls_message<'a, W>(m: &'a TlsMessage<'a>) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ move |out| match m {
+ TlsMessage::Handshake(ref m) => gen_tls_messagehandshake(m)(out),
+ TlsMessage::ChangeCipherSpec => gen_tls_changecipherspec()(out),
+ _ => Err(GenError::NotYetImplemented),
+ }
+}
+
+impl<'a> Serialize<Vec<u8>> for TlsMessage<'a> {
+ type Error = GenError;
+ fn serialize(&self) -> Result<Vec<u8>, Self::Error> {
+ gen_simple(gen_tls_message(self), Vec::new())
+ }
+}
+
+/// Serialize a TLS plaintext record
+///
+/// # Example
+///
+/// ```rust
+/// use cookie_factory::{gen_simple, GenError};
+/// use tls_parser::TlsPlaintext;
+/// use tls_parser::gen_tls_plaintext;
+///
+/// fn tls_message_to_vec(rec: &TlsPlaintext) -> Result<Vec<u8>, GenError> {
+/// gen_simple(gen_tls_plaintext(&rec), Vec::new())
+/// }
+/// ```
+pub fn gen_tls_plaintext<'a, W>(p: &'a TlsPlaintext) -> impl SerializeFn<W> + 'a
+where
+ W: Write + 'a,
+{
+ tuple((
+ be_u8(p.hdr.record_type.0),
+ be_u16(p.hdr.version.0),
+ length_be_u16(all(p.msg.iter().map(|m| gen_tls_message(m)))),
+ ))
+}
+
+impl<'a> Serialize<Vec<u8>> for TlsPlaintext<'a> {
+ type Error = GenError;
+ fn serialize(&self) -> Result<Vec<u8>, Self::Error> {
+ gen_simple(gen_tls_plaintext(self), Vec::new())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::tls_extensions::parse_tls_extension;
+ use hex_literal::hex;
+
+ const CH_DHE: &[u8] = include_bytes!("../assets/client_hello_dhe.bin");
+
+ #[test]
+ fn serialize_tagged_extension() {
+ let expected = &hex!("12 34 00 02 00 01");
+ let res =
+ gen_simple(tagged_extension(0x1234, be_u16(1)), Vec::new()).expect("serialize failed");
+ assert_eq!(&res, expected);
+ }
+
+ #[test]
+ fn serialize_extension_sni() {
+ let raw_sni = &hex!(
+ "
+00 00 00 14 00 12 00 00 0f 63 2e 64 69 73 71 75
+73 63 64 6e 2e 63 6f 6d
+"
+ );
+ let (_, ext) = parse_tls_extension(raw_sni).expect("could not parse sni extension");
+ if let TlsExtension::SNI(sni) = ext {
+ let res = gen_simple(gen_tls_ext_sni(&sni), Vec::new())
+ .expect("could not serialize sni extension");
+ assert_eq!(&res, raw_sni);
+ } else {
+ panic!("parsed extension has wrong type");
+ }
+ }
+
+ #[test]
+ fn serialize_tls_extensions() {
+ let ext = vec![TlsExtension::SNI(vec![(
+ SNIType::HostName,
+ b"www.google.com",
+ )])];
+
+ let res = gen_simple(gen_tls_extensions(&ext), Vec::new())
+ .expect("could not serialize extensions");
+ let v = [
+ 0x00, 0x17, // Extensions length (total)
+ 0x00, 0x00, // SNI tag
+ 0x00, 0x13, // SNI ext length
+ 0x00, 0x11, // SNI list length
+ // element 0:
+ 0x00, // type
+ 0x00, 0x0e, // length
+ 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
+ ];
+ assert_eq!(&res, &v);
+ }
+
+ #[test]
+ fn serialize_plaintext() {
+ let rand_data = [
+ 0xff, 0x21, 0xeb, 0x04, 0xc8, 0xa5, 0x38, 0x39, 0x9a, 0xcf, 0xb7, 0xa3, 0x82, 0x1f,
+ 0x82, 0x6c, 0x49, 0xbc, 0x8b, 0xb8, 0xa9, 0x03, 0x0a, 0x2d, 0xce, 0x38, 0x0b, 0xf4,
+ ];
+ let ciphers = vec![
+ 0xc030, 0xc02c, 0xc028, 0xc024, 0xc014, 0xc00a, 0x00a5, 0x00a3, 0x00a1, 0x009f, 0x006b,
+ 0x006a, 0x0069, 0x0068, 0x0039, 0x0038, 0x0037, 0x0036, 0x0088, 0x0087, 0x0086, 0x0085,
+ 0xc032, 0xc02e, 0xc02a, 0xc026, 0xc00f, 0xc005, 0x009d, 0x003d, 0x0035, 0x0084, 0xc02f,
+ 0xc02b, 0xc027, 0xc023, 0xc013, 0xc009, 0x00a4, 0x00a2, 0x00a0, 0x009e, 0x0067, 0x0040,
+ 0x003f, 0x003e, 0x0033, 0x0032, 0x0031, 0x0030, 0x009a, 0x0099, 0x0098, 0x0097, 0x0045,
+ 0x0044, 0x0043, 0x0042, 0xc031, 0xc02d, 0xc029, 0xc025, 0xc00e, 0xc004, 0x009c, 0x003c,
+ 0x002f, 0x0096, 0x0041, 0xc011, 0xc007, 0xc00c, 0xc002, 0x0005, 0x0004, 0xc012, 0xc008,
+ 0x0016, 0x0013, 0x0010, 0x000d, 0xc00d, 0xc003, 0x000a, 0x00ff,
+ ];
+ let comp = vec![TlsCompressionID(0x00)];
+
+ let expected = TlsPlaintext {
+ hdr: TlsRecordHeader {
+ record_type: TlsRecordType::Handshake,
+ version: TlsVersion::Tls10,
+ len: 215,
+ },
+ msg: vec![TlsMessage::Handshake(TlsMessageHandshake::ClientHello(
+ TlsClientHelloContents {
+ version: TlsVersion::Tls12,
+ rand_time: 0xb29d_d787,
+ rand_data: &rand_data,
+ session_id: None,
+ ciphers: ciphers.iter().map(|&x| TlsCipherSuiteID(x)).collect(),
+ comp,
+ ext: Some(&[]),
+ },
+ ))],
+ };
+
+ let res = expected
+ .serialize()
+ .expect("Could not serialize plaintext message");
+ let (_, res_reparse) =
+ parse_tls_plaintext(&res).expect("Could not parse gen_tls_plaintext output");
+ assert_eq!(res_reparse, expected);
+ }
+
+ #[test]
+ fn serialize_hellorequest() {
+ let m = TlsMessageHandshake::HelloRequest;
+
+ let res = m.serialize().expect("Could not serialize messages");
+ let v = [0, 0, 0, 0];
+ assert_eq!(&v[..], &res[..]);
+ }
+
+ #[test]
+ fn serialize_tls_ext() {
+ let ext = TlsExtension::SNI(vec![(SNIType::HostName, b"www.google.com")]);
+
+ let res =
+ gen_simple(gen_tls_extension(&ext), Vec::new()).expect("Could not serialize messages");
+ let v = [
+ 0x00, 0x00, // SNI tag
+ 0x00, 0x13, // SNI ext length
+ 0x00, 0x11, // SNI list length
+ // element 0:
+ 0x00, // type
+ 0x00, 0x0e, // length
+ 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
+ ];
+ assert_eq!(&v[..], &res[..]);
+ }
+
+ #[test]
+ fn serialize_clienthello() {
+ let rand_data = [
+ 0xff, 0x21, 0xeb, 0x04, 0xc8, 0xa5, 0x38, 0x39, 0x9a, 0xcf, 0xb7, 0xa3, 0x82, 0x1f,
+ 0x82, 0x6c, 0x49, 0xbc, 0x8b, 0xb8, 0xa9, 0x03, 0x0a, 0x2d, 0xce, 0x38, 0x0b, 0xf4,
+ ];
+ let ciphers = vec![0xc030, 0xc02c];
+ let comp = vec![TlsCompressionID(0x00)];
+
+ let m = TlsMessageHandshake::ClientHello(TlsClientHelloContents {
+ version: TlsVersion::Tls12,
+ rand_time: 0xb29d_d787,
+ rand_data: &rand_data,
+ session_id: None,
+ ciphers: ciphers.iter().map(|&x| TlsCipherSuiteID(x)).collect(),
+ comp,
+ ext: None,
+ });
+
+ let res = m.serialize().expect("Could not serialize messages");
+ let v = [
+ 0x01, 0x00, 0x00, 0x2d, 0x03, 0x03, // type, length, version
+ 0xb2, 0x9d, 0xd7, 0x87, // random time
+ 0xff, 0x21, 0xeb, 0x04, 0xc8, 0xa5, 0x38, 0x39, // random data
+ 0x9a, 0xcf, 0xb7, 0xa3, 0x82, 0x1f, 0x82, 0x6c, 0x49, 0xbc, 0x8b, 0xb8, 0xa9, 0x03,
+ 0x0a, 0x2d, 0xce, 0x38, 0x0b, 0xf4, 0x00, // session ID
+ 0x00, 0x04, 0xc0, 0x30, 0xc0, 0x2c, // ciphers
+ 0x01, 0x00, // compression
+ 0x00, 0x00, // extensions length
+ ];
+ assert_eq!(&v[..], &res[..]);
+ }
+
+ #[test]
+ fn serialize_serverhello() {
+ let rand_data = [
+ 0xff, 0x21, 0xeb, 0x04, 0xc8, 0xa5, 0x38, 0x39, 0x9a, 0xcf, 0xb7, 0xa3, 0x82, 0x1f,
+ 0x82, 0x6c, 0x49, 0xbc, 0x8b, 0xb8, 0xa9, 0x03, 0x0a, 0x2d, 0xce, 0x38, 0x0b, 0xf4,
+ ];
+
+ let m = TlsMessageHandshake::ServerHello(TlsServerHelloContents {
+ version: TlsVersion::Tls12,
+ rand_time: 0xb29d_d787,
+ rand_data: &rand_data,
+ session_id: None,
+ cipher: TlsCipherSuiteID(0xc030),
+ compression: TlsCompressionID(0),
+ ext: None,
+ });
+
+ let res = gen_simple(gen_tls_messagehandshake(&m), Vec::new())
+ .expect("Could not serialize message");
+ let v = [
+ 0x02, 0x00, 0x00, 0x28, 0x03, 0x03, // type, length, version
+ 0xb2, 0x9d, 0xd7, 0x87, // random time
+ 0xff, 0x21, 0xeb, 0x04, 0xc8, 0xa5, 0x38, 0x39, // random data
+ 0x9a, 0xcf, 0xb7, 0xa3, 0x82, 0x1f, 0x82, 0x6c, 0x49, 0xbc, 0x8b, 0xb8, 0xa9, 0x03,
+ 0x0a, 0x2d, 0xce, 0x38, 0x0b, 0xf4, 0x00, // session ID
+ 0xc0, 0x30, // cipher
+ 0x00, // compression
+ 0x00, 0x00, // extensions length
+ ];
+ assert_eq!(&v[..], &res[..]);
+ }
+
+ #[test]
+ fn read_serialize_clienthello_dhe() {
+ let (_, record) = parse_tls_plaintext(CH_DHE).expect("parsing failed");
+ let res = gen_simple(gen_tls_plaintext(&record), Vec::new())
+ .expect("Could not serialize message");
+ let (_, record2) = parse_tls_plaintext(&res).expect("re-parsing failed");
+ assert_eq!(record, record2);
+ }
+}
diff --git a/rust/vendor/tls-parser/src/tls_sign_hash.rs b/rust/vendor/tls-parser/src/tls_sign_hash.rs
new file mode 100644
index 0000000..be40778
--- /dev/null
+++ b/rust/vendor/tls-parser/src/tls_sign_hash.rs
@@ -0,0 +1,151 @@
+use nom::combinator::map;
+use nom::multi::length_data;
+use nom::number::streaming::be_u16;
+use nom::sequence::pair;
+use nom::IResult;
+use nom_derive::*;
+use rusticata_macros::newtype_enum;
+
+/// Hash algorithms, as defined in [RFC5246]
+#[derive(Clone, Debug, PartialEq, Eq, Nom)]
+pub struct HashAlgorithm(pub u8);
+
+newtype_enum! {
+impl display HashAlgorithm {
+ None = 0,
+ Md5 = 1,
+ Sha1 = 2,
+ Sha224 = 3,
+ Sha256 = 4,
+ Sha384 = 5,
+ Sha512 = 6,
+ Intrinsic = 8, // [RFC8422]
+}
+}
+
+/// Signature algorithms, as defined in [RFC5246]
+#[derive(Clone, Debug, PartialEq, Eq, Nom)]
+pub struct SignAlgorithm(pub u8);
+
+newtype_enum! {
+impl display SignAlgorithm {
+ Anonymous = 0,
+ Rsa = 1,
+ Dsa = 2,
+ Ecdsa = 3,
+ Ed25519 = 7, // [RFC8422]
+ Ed448 = 8, // [RFC8422]
+}
+}
+
+#[derive(Clone, PartialEq, Nom)]
+pub struct SignatureAndHashAlgorithm {
+ pub hash: HashAlgorithm,
+ pub sign: SignAlgorithm,
+}
+
+/// Signature algorithms, as defined in [RFC8446] 4.2.3
+#[derive(Debug, PartialEq, Eq, Nom)]
+pub struct SignatureScheme(pub u16);
+
+newtype_enum! {
+impl display SignatureScheme {
+ /* RSASSA-PKCS1-v1_5 algorithms */
+ rsa_pkcs1_sha256 = 0x0401,
+ rsa_pkcs1_sha384 = 0x0501,
+ rsa_pkcs1_sha512 = 0x0601,
+
+ /* ECDSA algorithms */
+ ecdsa_secp256r1_sha256 = 0x0403,
+ ecdsa_secp384r1_sha384 = 0x0503,
+ ecdsa_secp521r1_sha512 = 0x0603,
+
+ /* ShangMi (SM) Cipher Suites */
+ sm2sig_sm3 = 0x0708,
+
+ /* RSASSA-PSS algorithms with public key OID rsaEncryption */
+ rsa_pss_rsae_sha256 = 0x0804,
+ rsa_pss_rsae_sha384 = 0x0805,
+ rsa_pss_rsae_sha512 = 0x0806,
+
+ /* EdDSA algorithms */
+ ed25519 = 0x0807,
+ ed448 = 0x0808,
+
+ /* RSASSA-PSS algorithms with public key OID RSASSA-PSS */
+ rsa_pss_pss_sha256 = 0x0809,
+ rsa_pss_pss_sha384 = 0x080a,
+ rsa_pss_pss_sha512 = 0x080b,
+
+ /* Brainpool SignatureScheme Types for TLS 1.3 (RFC8734) */
+ ecdsa_brainpoolP256r1tls13_sha256 = 0x081a,
+ ecdsa_brainpoolP384r1tls13_sha384 = 0x081b,
+ ecdsa_brainpoolP512r1tls13_sha512 = 0x081c,
+
+ /* Legacy algorithms */
+ rsa_pkcs1_sha1 = 0x0201,
+ ecdsa_sha1 = 0x0203,
+}
+}
+
+impl SignatureScheme {
+ pub fn is_reserved(&self) -> bool {
+ self.0 >= 0xfe00 && self.0 < 0xff00
+ }
+
+ /// Get Hash algorithm (for tls <= 1.2) for legacy extension format
+ pub fn hash_alg(&self) -> u8 {
+ ((self.0 >> 8) & 0xff) as u8
+ }
+
+ /// Get Signature algorithm (for tls <= 1.2) for legacy extension format
+ pub fn sign_alg(&self) -> u8 {
+ (self.0 & 0xff) as u8
+ }
+}
+
+/// DigitallySigned structure from [RFC2246] section 4.7
+/// has no algorithm definition.
+/// This should be deprecated in favor if
+/// DigitallySigned structure from [RFC5246] section 4.7
+#[derive(Clone, PartialEq)]
+pub struct DigitallySigned<'a> {
+ pub alg: Option<SignatureAndHashAlgorithm>,
+ // pub alg: Option<u16>, // SignatureScheme
+ pub data: &'a [u8],
+}
+
+pub fn parse_digitally_signed_old(i: &[u8]) -> IResult<&[u8], DigitallySigned> {
+ map(length_data(be_u16), |data| DigitallySigned {
+ alg: None,
+ data,
+ })(i)
+}
+
+pub fn parse_digitally_signed(i: &[u8]) -> IResult<&[u8], DigitallySigned> {
+ let (i, hash) = HashAlgorithm::parse(i)?;
+ let (i, sign) = SignAlgorithm::parse(i)?;
+ let (i, data) = length_data(be_u16)(i)?;
+ let signed = DigitallySigned {
+ alg: Some(SignatureAndHashAlgorithm { hash, sign }),
+ data,
+ };
+ Ok((i, signed))
+}
+
+/// Parse DigitallySigned object, depending on the `ext` parameter which should
+/// be true if the TLS client has sent the `signature_algorithms` extension
+pub fn parse_content_and_signature<'a, F, T: 'a>(
+ i: &'a [u8],
+ fun: F,
+ ext: bool,
+) -> IResult<&'a [u8], (T, DigitallySigned)>
+where
+ F: Fn(&'a [u8]) -> IResult<&[u8], T>,
+{
+ if ext {
+ pair(fun, parse_digitally_signed)(i)
+ } else {
+ pair(fun, parse_digitally_signed_old)(i)
+ }
+}
diff --git a/rust/vendor/tls-parser/src/tls_states.rs b/rust/vendor/tls-parser/src/tls_states.rs
new file mode 100644
index 0000000..ccd1b4b
--- /dev/null
+++ b/rust/vendor/tls-parser/src/tls_states.rs
@@ -0,0 +1,132 @@
+use crate::tls::*;
+use crate::tls_alert::TlsAlertSeverity;
+
+/// Error types for the state machine
+pub enum StateChangeError {
+ InvalidTransition,
+ ParseError,
+}
+
+/// TLS machine possible states
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum TlsState {
+ None,
+ ClientHello,
+ AskResumeSession,
+ ResumeSession,
+ ServerHello,
+ Certificate,
+ CertificateSt,
+ ServerKeyExchange,
+ ServerHelloDone,
+ ClientKeyExchange,
+ ClientChangeCipherSpec,
+
+ CRCertRequest,
+ CRHelloDone,
+ CRCert,
+ CRClientKeyExchange,
+ CRCertVerify,
+
+ NoCertSKE,
+ NoCertHelloDone,
+ NoCertCKE,
+
+ PskHelloDone,
+ PskCKE,
+
+ SessionEncrypted,
+
+ Alert,
+
+ Finished,
+
+ Invalid,
+}
+
+#[rustfmt::skip]
+fn tls_state_transition_handshake(state: TlsState, msg: &TlsMessageHandshake, to_server:bool) -> Result<TlsState,StateChangeError> {
+ match (state,msg,to_server) {
+ (TlsState::None, &TlsMessageHandshake::ClientHello(ref msg), true) => {
+ match msg.session_id {
+ Some(_) => Ok(TlsState::AskResumeSession),
+ _ => Ok(TlsState::ClientHello)
+ }
+ },
+ // Server certificate
+ (TlsState::ClientHello, &TlsMessageHandshake::ServerHello(_), false) => Ok(TlsState::ServerHello),
+ (TlsState::ServerHello, &TlsMessageHandshake::Certificate(_), false) => Ok(TlsState::Certificate),
+ // Server certificate, no client certificate requested
+ (TlsState::Certificate, &TlsMessageHandshake::ServerKeyExchange(_), false) => Ok(TlsState::ServerKeyExchange),
+ (TlsState::Certificate, &TlsMessageHandshake::CertificateStatus(_), false) => Ok(TlsState::CertificateSt),
+ (TlsState::CertificateSt, &TlsMessageHandshake::ServerKeyExchange(_), false) => Ok(TlsState::ServerKeyExchange),
+ (TlsState::ServerKeyExchange,&TlsMessageHandshake::ServerDone(_), false) => Ok(TlsState::ServerHelloDone),
+ (TlsState::ServerHelloDone ,&TlsMessageHandshake::ClientKeyExchange(_), true) => Ok(TlsState::ClientKeyExchange),
+ // Server certificate, client certificate requested
+ (TlsState::Certificate, &TlsMessageHandshake::CertificateRequest(_), false)=> Ok(TlsState::CRCertRequest),
+ (TlsState::ServerKeyExchange,&TlsMessageHandshake::CertificateRequest(_), false)=> Ok(TlsState::CRCertRequest),
+ (TlsState::CRCertRequest, &TlsMessageHandshake::ServerDone(_), false) => Ok(TlsState::CRHelloDone),
+ (TlsState::CRHelloDone, &TlsMessageHandshake::Certificate(_), true) => Ok(TlsState::CRCert),
+ (TlsState::CRCert, &TlsMessageHandshake::ClientKeyExchange(_), true) => Ok(TlsState::CRClientKeyExchange),
+ (TlsState::CRClientKeyExchange, &TlsMessageHandshake::CertificateVerify(_), _) => Ok(TlsState::CRCertVerify),
+ // Server has no certificate (but accepts anonymous)
+ (TlsState::ServerHello, &TlsMessageHandshake::ServerKeyExchange(_), false) => Ok(TlsState::NoCertSKE),
+ (TlsState::NoCertSKE, &TlsMessageHandshake::ServerDone(_), false) => Ok(TlsState::NoCertHelloDone),
+ (TlsState::NoCertHelloDone, &TlsMessageHandshake::ClientKeyExchange(_), true) => Ok(TlsState::NoCertCKE),
+ // PSK
+ (TlsState::Certificate, &TlsMessageHandshake::ServerDone(_), false) => Ok(TlsState::PskHelloDone),
+ (TlsState::PskHelloDone, &TlsMessageHandshake::ClientKeyExchange(_), true) => Ok(TlsState::PskCKE),
+ // Resuming session
+ (TlsState::AskResumeSession, &TlsMessageHandshake::ServerHello(_), false) => Ok(TlsState::ResumeSession),
+ // Resume session failed
+ (TlsState::ResumeSession, &TlsMessageHandshake::Certificate(_), false) => Ok(TlsState::Certificate),
+ // TLS 1.3 Draft 18 1-RTT
+ // Re-use the ClientChangeCipherSpec state to indicate the next message will be encrypted
+ (TlsState::ClientHello, &TlsMessageHandshake::ServerHelloV13Draft18(_), false) => Ok(TlsState::ClientChangeCipherSpec),
+ // Hello requests must be accepted at any time (except start), but ignored [RFC5246] 7.4.1.1
+ (TlsState::None, &TlsMessageHandshake::HelloRequest, _) => Err(StateChangeError::InvalidTransition),
+ (s, &TlsMessageHandshake::HelloRequest, _) => Ok(s),
+ // All other transitions are considered invalid
+ _ => Err(StateChangeError::InvalidTransition),
+ }
+}
+
+/// Update the TLS state machine, doing one transition
+///
+/// Given the previous state and the parsed message, return the new state or a state machine error.
+///
+/// This state machine only implements the TLS handshake.
+///
+/// Some transitions only check the new message type, while some others must match the content
+/// (for example, to check if the client asked to resume a session).
+///
+/// If the previous state is `Invalid`, the state machine will not return an error, but keep the
+/// same `Invalid` state. This is used to raise error only once if the state machine keeps being
+/// updated by new messages.
+#[rustfmt::skip]
+pub fn tls_state_transition(state: TlsState, msg: &TlsMessage, to_server:bool) -> Result<TlsState,StateChangeError> {
+ match (state,msg,to_server) {
+ (TlsState::Invalid,_,_) => Ok(TlsState::Invalid),
+ (TlsState::Finished,_,_) => Ok(TlsState::Invalid),
+ (_,&TlsMessage::Handshake(ref m),_) => tls_state_transition_handshake(state,m,to_server),
+ // Server certificate
+ (TlsState::ClientKeyExchange, &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
+ (TlsState::ClientChangeCipherSpec,&TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::SessionEncrypted),
+ // Server certificate, client certificate requested
+ (TlsState::CRClientKeyExchange, &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
+ (TlsState::CRCertVerify, &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
+ // No server certificate
+ (TlsState::NoCertCKE, &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
+ // PSK
+ (TlsState::PskCKE, &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
+ // Resume session
+ (TlsState::ResumeSession, &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
+ // 0-rtt
+ (TlsState::AskResumeSession, &TlsMessage::ChangeCipherSpec, true) => Ok(TlsState::AskResumeSession),
+ // non-fatal alerts
+ (s, &TlsMessage::Alert(ref a), _) => {
+ if a.severity == TlsAlertSeverity::Warning { Ok(s) } else { Ok(TlsState::Finished) }
+ },
+ (_,_,_) => Err(StateChangeError::InvalidTransition),
+ }
+}
diff --git a/rust/vendor/tls-parser/tests/certificate_transparency.rs b/rust/vendor/tls-parser/tests/certificate_transparency.rs
new file mode 100644
index 0000000..4a040a9
--- /dev/null
+++ b/rust/vendor/tls-parser/tests/certificate_transparency.rs
@@ -0,0 +1,95 @@
+#[macro_use]
+extern crate pretty_assertions;
+
+extern crate nom;
+extern crate tls_parser;
+
+mod certificate_transparency {
+ use tls_parser::*;
+
+ static SCT_LIST: &[u8] = &[
+ 0x00, 0xf0, 0x00, 0x76, 0x00, 0xf6, 0x5c, 0x94, 0x2f, 0xd1, 0x77, 0x30, 0x22, 0x14, 0x54,
+ 0x18, 0x08, 0x30, 0x94, 0x56, 0x8e, 0xe3, 0x4d, 0x13, 0x19, 0x33, 0xbf, 0xdf, 0x0c, 0x2f,
+ 0x20, 0x0b, 0xcc, 0x4e, 0xf1, 0x64, 0xe3, 0x00, 0x00, 0x01, 0x72, 0x53, 0x4b, 0x97, 0xa5,
+ 0x00, 0x00, 0x04, 0x03, 0x00, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xc6, 0x2d, 0xa9, 0x45,
+ 0xd2, 0x81, 0xfd, 0xda, 0x9f, 0xf3, 0xf8, 0xa4, 0x18, 0xb4, 0x4d, 0x2f, 0x7c, 0x23, 0x60,
+ 0xb5, 0x6a, 0xb9, 0x51, 0x88, 0x9c, 0x38, 0x1b, 0x36, 0xf8, 0xa9, 0xf2, 0x1d, 0x02, 0x20,
+ 0x00, 0xe2, 0xfc, 0xde, 0xbc, 0x91, 0x08, 0x29, 0x46, 0x86, 0x08, 0x89, 0x5b, 0x62, 0xd4,
+ 0x45, 0x3e, 0x91, 0xdd, 0x39, 0x76, 0xb7, 0xa6, 0xe4, 0xae, 0xd4, 0xd2, 0x38, 0x50, 0xe9,
+ 0xc7, 0xd0, 0x00, 0x76, 0x00, 0x5c, 0xdc, 0x43, 0x92, 0xfe, 0xe6, 0xab, 0x45, 0x44, 0xb1,
+ 0x5e, 0x9a, 0xd4, 0x56, 0xe6, 0x10, 0x37, 0xfb, 0xd5, 0xfa, 0x47, 0xdc, 0xa1, 0x73, 0x94,
+ 0xb2, 0x5e, 0xe6, 0xf6, 0xc7, 0x0e, 0xca, 0x00, 0x00, 0x01, 0x72, 0x53, 0x4b, 0x97, 0xa0,
+ 0x00, 0x00, 0x04, 0x03, 0x00, 0x47, 0x30, 0x45, 0x02, 0x20, 0x35, 0x6c, 0x91, 0x1f, 0xb3,
+ 0x22, 0x79, 0xf2, 0x65, 0x95, 0x53, 0xcf, 0x3a, 0x36, 0xd7, 0xac, 0xde, 0xa1, 0xf4, 0xb1,
+ 0xa9, 0x2e, 0xdd, 0x46, 0x0d, 0x96, 0xff, 0x1b, 0xda, 0x93, 0x4e, 0xe8, 0x02, 0x21, 0x00,
+ 0xee, 0xed, 0x93, 0x37, 0xba, 0x12, 0xdb, 0x44, 0x67, 0x7e, 0x09, 0xa4, 0x5f, 0xd6, 0x66,
+ 0x6c, 0x7b, 0x02, 0xb8, 0x63, 0x1f, 0xb6, 0xbf, 0x91, 0x53, 0x95, 0xb6, 0xf9, 0xd6, 0xfd,
+ 0x45, 0x2d,
+ ];
+
+ #[test]
+ fn test_ct_parse_signed_certificate_timestamp_list() {
+ let empty = &b""[..];
+ let res = parse_ct_signed_certificate_timestamp_list(SCT_LIST).unwrap();
+ let id1 = &[
+ 0xf6, 0x5c, 0x94, 0x2f, 0xd1, 0x77, 0x30, 0x22, 0x14, 0x54, 0x18, 0x08, 0x30, 0x94,
+ 0x56, 0x8e, 0xe3, 0x4d, 0x13, 0x19, 0x33, 0xbf, 0xdf, 0x0c, 0x2f, 0x20, 0x0b, 0xcc,
+ 0x4e, 0xf1, 0x64, 0xe3,
+ ];
+ let id2 = &[
+ 0x5c, 0xdc, 0x43, 0x92, 0xfe, 0xe6, 0xab, 0x45, 0x44, 0xb1, 0x5e, 0x9a, 0xd4, 0x56,
+ 0xe6, 0x10, 0x37, 0xfb, 0xd5, 0xfa, 0x47, 0xdc, 0xa1, 0x73, 0x94, 0xb2, 0x5e, 0xe6,
+ 0xf6, 0xc7, 0x0e, 0xca,
+ ];
+ let signature1 = DigitallySigned {
+ alg: Some(SignatureAndHashAlgorithm {
+ hash: HashAlgorithm::Sha256,
+ sign: SignAlgorithm::Ecdsa,
+ }),
+ data: &[
+ 0x30, 0x45, 0x02, 0x21, 0x00, 0xc6, 0x2d, 0xa9, 0x45, 0xd2, 0x81, 0xfd, 0xda, 0x9f,
+ 0xf3, 0xf8, 0xa4, 0x18, 0xb4, 0x4d, 0x2f, 0x7c, 0x23, 0x60, 0xb5, 0x6a, 0xb9, 0x51,
+ 0x88, 0x9c, 0x38, 0x1b, 0x36, 0xf8, 0xa9, 0xf2, 0x1d, 0x02, 0x20, 0x00, 0xe2, 0xfc,
+ 0xde, 0xbc, 0x91, 0x08, 0x29, 0x46, 0x86, 0x08, 0x89, 0x5b, 0x62, 0xd4, 0x45, 0x3e,
+ 0x91, 0xdd, 0x39, 0x76, 0xb7, 0xa6, 0xe4, 0xae, 0xd4, 0xd2, 0x38, 0x50, 0xe9, 0xc7,
+ 0xd0,
+ ],
+ };
+ let signature2 = DigitallySigned {
+ alg: Some(SignatureAndHashAlgorithm {
+ hash: HashAlgorithm::Sha256,
+ sign: SignAlgorithm::Ecdsa,
+ }),
+ data: &[
+ 0x30, 0x45, 0x02, 0x20, 0x35, 0x6c, 0x91, 0x1f, 0xb3, 0x22, 0x79, 0xf2, 0x65, 0x95,
+ 0x53, 0xcf, 0x3a, 0x36, 0xd7, 0xac, 0xde, 0xa1, 0xf4, 0xb1, 0xa9, 0x2e, 0xdd, 0x46,
+ 0x0d, 0x96, 0xff, 0x1b, 0xda, 0x93, 0x4e, 0xe8, 0x02, 0x21, 0x00, 0xee, 0xed, 0x93,
+ 0x37, 0xba, 0x12, 0xdb, 0x44, 0x67, 0x7e, 0x09, 0xa4, 0x5f, 0xd6, 0x66, 0x6c, 0x7b,
+ 0x02, 0xb8, 0x63, 0x1f, 0xb6, 0xbf, 0x91, 0x53, 0x95, 0xb6, 0xf9, 0xd6, 0xfd, 0x45,
+ 0x2d,
+ ],
+ };
+ assert_eq!(
+ res,
+ (
+ empty,
+ vec![
+ SignedCertificateTimestamp {
+ version: CtVersion::V1,
+ id: CtLogID { key_id: id1 },
+ timestamp: 1590535362469,
+ extensions: CtExtensions(empty),
+ signature: signature1
+ },
+ SignedCertificateTimestamp {
+ version: CtVersion::V1,
+ id: CtLogID { key_id: id2 },
+ timestamp: 1590535362464,
+ extensions: CtExtensions(empty),
+ signature: signature2
+ }
+ ]
+ )
+ );
+ }
+}
diff --git a/rust/vendor/tls-parser/tests/tls_dh.rs b/rust/vendor/tls-parser/tests/tls_dh.rs
new file mode 100644
index 0000000..02bc166
--- /dev/null
+++ b/rust/vendor/tls-parser/tests/tls_dh.rs
@@ -0,0 +1,145 @@
+mod tls_dh {
+ use nom::sequence::pair;
+ use tls_parser::*;
+
+ #[rustfmt::skip]
+static ECDHE_PARAMS: &[u8] = &[
+ 0x03, 0x00, 0x19, 0x85, 0x04, 0x01, 0xd1, 0x50, 0x12, 0xf4, 0xc4, 0xcf, 0xd4, 0xc2, 0x1f, 0xe8,
+ 0xf6, 0x85, 0xdc, 0xde, 0x0b, 0xeb, 0x3c, 0x0d, 0x0f, 0x97, 0x29, 0x36, 0x63, 0xc6, 0xc1, 0x3b,
+ 0xfd, 0x38, 0xce, 0xde, 0x43, 0x7f, 0x7d, 0x57, 0x64, 0x54, 0x6f, 0x89, 0x3c, 0xe7, 0x5e, 0x28,
+ 0x9e, 0x9d, 0x24, 0xca, 0x07, 0x63, 0xd5, 0x03, 0x30, 0x8b, 0xd8, 0x1a, 0xae, 0xb6, 0xa8, 0x5f,
+ 0x10, 0x87, 0x81, 0x29, 0x1b, 0xef, 0xbd, 0x00, 0xeb, 0x29, 0x37, 0xb3, 0xc3, 0xda, 0x8e, 0xad,
+ 0xf3, 0x9c, 0x10, 0xe3, 0x93, 0xeb, 0x0a, 0x53, 0x14, 0xea, 0x3c, 0x05, 0xb7, 0xc1, 0x6b, 0x79,
+ 0xca, 0xfc, 0x9a, 0x5b, 0xc3, 0xaf, 0xf2, 0xdd, 0x9f, 0xdd, 0x07, 0xf5, 0x07, 0xef, 0xb4, 0x24,
+ 0xac, 0xdb, 0xd2, 0x0d, 0x65, 0x37, 0x96, 0xa0, 0x15, 0xef, 0x7c, 0x6d, 0x66, 0x63, 0x0d, 0x41,
+ 0x1d, 0xd7, 0x90, 0x05, 0x66, 0xcf, 0x79, 0x0c, 0x03, 0x02, 0x01, 0x01, 0x00, 0x7c, 0xa7, 0x5f,
+ 0x73, 0x77, 0x2c, 0x92, 0x4c, 0xe4, 0xa7, 0x67, 0x86, 0x76, 0xf2, 0xa3, 0xf8, 0xd1, 0x9d, 0xca,
+ 0x4f, 0x71, 0xd1, 0x67, 0xf4, 0xbe, 0x7e, 0xb3, 0x60, 0xc4, 0xf1, 0x6e, 0x90, 0x22, 0x97, 0xe9,
+ 0xc2, 0x43, 0xc9, 0xfb, 0x46, 0x21, 0xd4, 0xe9, 0xed, 0xdc, 0x46, 0x5b, 0x3e, 0x4c, 0xfb, 0xf2,
+ 0xeb, 0x3f, 0x09, 0x4e, 0x59, 0x5f, 0x6f, 0x60, 0x50, 0x8a, 0x80, 0x50, 0xa7, 0xc3, 0xb9, 0xf0,
+ 0xd1, 0x80, 0xb0, 0x1b, 0x11, 0x53, 0xe4, 0xac, 0x45, 0xa8, 0x75, 0x59, 0x55, 0x1a, 0x20, 0xa5,
+ 0xbb, 0x23, 0xb6, 0x1c, 0x39, 0xa8, 0x4e, 0x62, 0x57, 0xef, 0x4f, 0x11, 0xce, 0x64, 0x87, 0x9b,
+ 0x5a, 0xb8, 0x06, 0xf1, 0x62, 0x63, 0x3d, 0x13, 0x46, 0x72, 0x79, 0x7e, 0x65, 0x5c, 0xb4, 0x0a,
+ 0xe3, 0x63, 0x13, 0x05, 0xc9, 0xaa, 0xc3, 0x93, 0x9b, 0x69, 0x37, 0x04, 0xa6, 0x7b, 0x69, 0xa9,
+ 0x72, 0x67, 0x32, 0x9d, 0xc9, 0x53, 0x05, 0xe5, 0x18, 0x00, 0x73, 0xcb, 0x40, 0xd8, 0x86, 0x81,
+ 0x01, 0x78, 0x36, 0x8f, 0x62, 0x94, 0xb4, 0x88, 0x27, 0xdb, 0x8e, 0xe4, 0x76, 0x56, 0x1d, 0xac,
+ 0x7d, 0x36, 0x4c, 0xb4, 0xad, 0x4c, 0xe0, 0x21, 0x1f, 0xd5, 0x2d, 0x30, 0xa0, 0x78, 0xba, 0x28,
+ 0x0b, 0xb4, 0x6d, 0xf1, 0x95, 0x41, 0x11, 0xdb, 0x64, 0xaf, 0x11, 0xa2, 0x9b, 0x45, 0x07, 0x42,
+ 0x95, 0xf1, 0xe4, 0x0a, 0x16, 0x0c, 0x7f, 0xa7, 0x96, 0xc1, 0x91, 0xf0, 0x7c, 0xf7, 0x67, 0xe6,
+ 0x1c, 0xbd, 0x1d, 0xcb, 0xbc, 0x42, 0x2a, 0x47, 0x35, 0x28, 0x96, 0xc3, 0x08, 0x48, 0x7d, 0xe9,
+ 0xf1, 0x42, 0x00, 0xee, 0xd5, 0x0e, 0xd4, 0x08, 0xd6, 0x34, 0x15, 0xd6, 0x7c, 0x4b, 0xc5, 0x23,
+ 0xf4, 0x8c, 0xfa, 0x70, 0xd8, 0x60, 0x46, 0xd2, 0xa3, 0xba, 0x75, 0xa4, 0x8f
+];
+
+ #[test]
+ fn test_tls_ecdhe_params() {
+ let empty = &b""[..];
+ let bytes = ECDHE_PARAMS;
+ let point_data = &bytes[4..137];
+ let expected1 = ServerECDHParams {
+ curve_params: ECParameters {
+ curve_type: ECCurveType::NamedGroup,
+ params_content: ECParametersContent::NamedGroup(NamedGroup::Secp521r1),
+ },
+ public: ECPoint { point: point_data },
+ };
+ let expected2 = DigitallySigned {
+ alg: Some(SignatureAndHashAlgorithm {
+ hash: HashAlgorithm::Sha1,
+ sign: SignAlgorithm::Rsa,
+ }),
+ data: &bytes[141..],
+ };
+ let res = pair(parse_ecdh_params, parse_digitally_signed)(bytes);
+ assert_eq!(res, Ok((empty, (expected1, expected2))));
+ }
+
+ #[rustfmt::skip]
+static DHE_PARAMS: &[u8] = &[
+ 0x01, 0x00, 0xad, 0x10, 0x7e, 0x1e, 0x91, 0x23, 0xa9, 0xd0, 0xd6, 0x60, 0xfa, 0xa7, 0x95, 0x59,
+ 0xc5, 0x1f, 0xa2, 0x0d, 0x64, 0xe5, 0x68, 0x3b, 0x9f, 0xd1, 0xb5, 0x4b, 0x15, 0x97, 0xb6, 0x1d,
+ 0x0a, 0x75, 0xe6, 0xfa, 0x14, 0x1d, 0xf9, 0x5a, 0x56, 0xdb, 0xaf, 0x9a, 0x3c, 0x40, 0x7b, 0xa1,
+ 0xdf, 0x15, 0xeb, 0x3d, 0x68, 0x8a, 0x30, 0x9c, 0x18, 0x0e, 0x1d, 0xe6, 0xb8, 0x5a, 0x12, 0x74,
+ 0xa0, 0xa6, 0x6d, 0x3f, 0x81, 0x52, 0xad, 0x6a, 0xc2, 0x12, 0x90, 0x37, 0xc9, 0xed, 0xef, 0xda,
+ 0x4d, 0xf8, 0xd9, 0x1e, 0x8f, 0xef, 0x55, 0xb7, 0x39, 0x4b, 0x7a, 0xd5, 0xb7, 0xd0, 0xb6, 0xc1,
+ 0x22, 0x07, 0xc9, 0xf9, 0x8d, 0x11, 0xed, 0x34, 0xdb, 0xf6, 0xc6, 0xba, 0x0b, 0x2c, 0x8b, 0xbc,
+ 0x27, 0xbe, 0x6a, 0x00, 0xe0, 0xa0, 0xb9, 0xc4, 0x97, 0x08, 0xb3, 0xbf, 0x8a, 0x31, 0x70, 0x91,
+ 0x88, 0x36, 0x81, 0x28, 0x61, 0x30, 0xbc, 0x89, 0x85, 0xdb, 0x16, 0x02, 0xe7, 0x14, 0x41, 0x5d,
+ 0x93, 0x30, 0x27, 0x82, 0x73, 0xc7, 0xde, 0x31, 0xef, 0xdc, 0x73, 0x10, 0xf7, 0x12, 0x1f, 0xd5,
+ 0xa0, 0x74, 0x15, 0x98, 0x7d, 0x9a, 0xdc, 0x0a, 0x48, 0x6d, 0xcd, 0xf9, 0x3a, 0xcc, 0x44, 0x32,
+ 0x83, 0x87, 0x31, 0x5d, 0x75, 0xe1, 0x98, 0xc6, 0x41, 0xa4, 0x80, 0xcd, 0x86, 0xa1, 0xb9, 0xe5,
+ 0x87, 0xe8, 0xbe, 0x60, 0xe6, 0x9c, 0xc9, 0x28, 0xb2, 0xb9, 0xc5, 0x21, 0x72, 0xe4, 0x13, 0x04,
+ 0x2e, 0x9b, 0x23, 0xf1, 0x0b, 0x0e, 0x16, 0xe7, 0x97, 0x63, 0xc9, 0xb5, 0x3d, 0xcf, 0x4b, 0xa8,
+ 0x0a, 0x29, 0xe3, 0xfb, 0x73, 0xc1, 0x6b, 0x8e, 0x75, 0xb9, 0x7e, 0xf3, 0x63, 0xe2, 0xff, 0xa3,
+ 0x1f, 0x71, 0xcf, 0x9d, 0xe5, 0x38, 0x4e, 0x71, 0xb8, 0x1c, 0x0a, 0xc4, 0xdf, 0xfe, 0x0c, 0x10,
+ 0xe6, 0x4f, 0x01, 0x00, 0xac, 0x40, 0x32, 0xef, 0x4f, 0x2d, 0x9a, 0xe3, 0x9d, 0xf3, 0x0b, 0x5c,
+ 0x8f, 0xfd, 0xac, 0x50, 0x6c, 0xde, 0xbe, 0x7b, 0x89, 0x99, 0x8c, 0xaf, 0x74, 0x86, 0x6a, 0x08,
+ 0xcf, 0xe4, 0xff, 0xe3, 0xa6, 0x82, 0x4a, 0x4e, 0x10, 0xb9, 0xa6, 0xf0, 0xdd, 0x92, 0x1f, 0x01,
+ 0xa7, 0x0c, 0x4a, 0xfa, 0xab, 0x73, 0x9d, 0x77, 0x00, 0xc2, 0x9f, 0x52, 0xc5, 0x7d, 0xb1, 0x7c,
+ 0x62, 0x0a, 0x86, 0x52, 0xbe, 0x5e, 0x90, 0x01, 0xa8, 0xd6, 0x6a, 0xd7, 0xc1, 0x76, 0x69, 0x10,
+ 0x19, 0x99, 0x02, 0x4a, 0xf4, 0xd0, 0x27, 0x27, 0x5a, 0xc1, 0x34, 0x8b, 0xb8, 0xa7, 0x62, 0xd0,
+ 0x52, 0x1b, 0xc9, 0x8a, 0xe2, 0x47, 0x15, 0x04, 0x22, 0xea, 0x1e, 0xd4, 0x09, 0x93, 0x9d, 0x54,
+ 0xda, 0x74, 0x60, 0xcd, 0xb5, 0xf6, 0xc6, 0xb2, 0x50, 0x71, 0x7c, 0xbe, 0xf1, 0x80, 0xeb, 0x34,
+ 0x11, 0x8e, 0x98, 0xd1, 0x19, 0x52, 0x9a, 0x45, 0xd6, 0xf8, 0x34, 0x56, 0x6e, 0x30, 0x25, 0xe3,
+ 0x16, 0xa3, 0x30, 0xef, 0xbb, 0x77, 0xa8, 0x6f, 0x0c, 0x1a, 0xb1, 0x5b, 0x05, 0x1a, 0xe3, 0xd4,
+ 0x28, 0xc8, 0xf8, 0xac, 0xb7, 0x0a, 0x81, 0x37, 0x15, 0x0b, 0x8e, 0xeb, 0x10, 0xe1, 0x83, 0xed,
+ 0xd1, 0x99, 0x63, 0xdd, 0xd9, 0xe2, 0x63, 0xe4, 0x77, 0x05, 0x89, 0xef, 0x6a, 0xa2, 0x1e, 0x7f,
+ 0x5f, 0x2f, 0xf3, 0x81, 0xb5, 0x39, 0xcc, 0xe3, 0x40, 0x9d, 0x13, 0xcd, 0x56, 0x6a, 0xfb, 0xb4,
+ 0x8d, 0x6c, 0x01, 0x91, 0x81, 0xe1, 0xbc, 0xfe, 0x94, 0xb3, 0x02, 0x69, 0xed, 0xfe, 0x72, 0xfe,
+ 0x9b, 0x6a, 0xa4, 0xbd, 0x7b, 0x5a, 0x0f, 0x1c, 0x71, 0xcf, 0xff, 0x4c, 0x19, 0xc4, 0x18, 0xe1,
+ 0xf6, 0xec, 0x01, 0x79, 0x81, 0xbc, 0x08, 0x7f, 0x2a, 0x70, 0x65, 0xb3, 0x84, 0xb8, 0x90, 0xd3,
+ 0x19, 0x1f, 0x2b, 0xfa, 0x01, 0x00, 0x6f, 0x45, 0x37, 0xd8, 0xe5, 0x74, 0x44, 0xa4, 0xd0, 0xea,
+ 0xa7, 0x37, 0x49, 0xb3, 0x06, 0xfa, 0xe6, 0x2e, 0x97, 0x18, 0x84, 0x13, 0x57, 0xd5, 0x5f, 0x87,
+ 0xab, 0xc1, 0x4b, 0xc7, 0xac, 0x14, 0x52, 0x23, 0x1b, 0xb0, 0x64, 0xef, 0x0b, 0x52, 0x6d, 0x8f,
+ 0xf3, 0x79, 0x1f, 0x91, 0xc0, 0x44, 0xd6, 0x07, 0xeb, 0x0a, 0xf2, 0x10, 0x96, 0xf1, 0x54, 0xa3,
+ 0x11, 0x89, 0xb7, 0xdc, 0x87, 0xf1, 0x8f, 0x24, 0xb7, 0x08, 0xc5, 0xf4, 0x19, 0x67, 0x2c, 0x63,
+ 0xde, 0xc3, 0x2d, 0x4e, 0xea, 0xbc, 0x4a, 0x55, 0x8a, 0x45, 0x7b, 0x57, 0xe2, 0x8a, 0xb1, 0x29,
+ 0x0c, 0xcb, 0x41, 0xc3, 0xf0, 0x07, 0x85, 0x14, 0x35, 0x54, 0x35, 0x04, 0x69, 0xa4, 0x87, 0x9a,
+ 0x97, 0x0f, 0x4f, 0xb8, 0x7c, 0x36, 0xa5, 0xd8, 0x89, 0xc8, 0x41, 0x62, 0xd8, 0x27, 0x30, 0xf5,
+ 0x1b, 0x86, 0x46, 0xb6, 0x14, 0xa2, 0xea, 0x7c, 0xac, 0x62, 0xc1, 0xf8, 0x26, 0xf0, 0x63, 0x1e,
+ 0x73, 0x74, 0xb2, 0xa0, 0x77, 0xd1, 0x2b, 0xeb, 0x79, 0x77, 0x65, 0xd9, 0x60, 0x50, 0x5d, 0x2b,
+ 0x3b, 0x3c, 0xa2, 0xb5, 0x6a, 0x89, 0x2b, 0xb6, 0x92, 0xb0, 0x7e, 0x22, 0x03, 0xfe, 0xf5, 0x53,
+ 0x90, 0x1f, 0x7d, 0xe9, 0x42, 0x82, 0xfa, 0x92, 0xb9, 0x7b, 0x15, 0xd4, 0xa6, 0x98, 0xe4, 0xf3,
+ 0xee, 0xb6, 0xcc, 0xaa, 0xb2, 0xa6, 0xdf, 0x9a, 0xb9, 0x72, 0xcf, 0x5b, 0x76, 0x6b, 0xd5, 0x04,
+ 0x98, 0x23, 0xa8, 0x29, 0xdf, 0x2a, 0xd9, 0xb7, 0x1e, 0xbc, 0xe3, 0x4a, 0x93, 0x08, 0x3a, 0xc4,
+ 0x66, 0x1f, 0x2c, 0x94, 0x4d, 0x7a, 0xe6, 0xa9, 0x26, 0x40, 0x64, 0x2b, 0x31, 0xd7, 0xb5, 0x3b,
+ 0x4e, 0xc5, 0x78, 0xe0, 0x90, 0x15, 0xaa, 0x95, 0x80, 0xc3, 0x22, 0x67, 0x5c, 0x21, 0x4c, 0xb7,
+ 0xe3, 0x9f, 0xf2, 0xdb, 0x66, 0x97, 0x06, 0x01, 0x01, 0x00, 0x4e, 0x76, 0x32, 0x0e, 0xa2, 0xb2,
+ 0x9f, 0x1c, 0xe0, 0x54, 0xff, 0x5c, 0xc7, 0xc4, 0x1b, 0xbc, 0x82, 0x8c, 0xfa, 0x05, 0xb7, 0xf3,
+ 0x58, 0x0a, 0xa9, 0x12, 0x41, 0xb2, 0x4a, 0xfa, 0x3f, 0x0a, 0xc2, 0x30, 0xf3, 0xd7, 0x23, 0x28,
+ 0xdf, 0x67, 0x51, 0x2f, 0x74, 0xef, 0x73, 0xe6, 0x9b, 0xf1, 0x2f, 0xe8, 0xda, 0x56, 0xba, 0x2a,
+ 0x3f, 0xfe, 0x4c, 0xfb, 0x1c, 0xe5, 0xdd, 0x41, 0x1d, 0x5d, 0x20, 0xc1, 0x75, 0xc3, 0x62, 0x14,
+ 0xa5, 0x32, 0x55, 0x2f, 0xfa, 0xf0, 0x8e, 0x9f, 0x95, 0x02, 0xfe, 0x15, 0x6f, 0x97, 0x18, 0xa1,
+ 0x2f, 0xaf, 0xb0, 0x03, 0xcb, 0xac, 0x91, 0x36, 0x12, 0xd9, 0xea, 0x39, 0x9c, 0x40, 0xf5, 0xbd,
+ 0x69, 0x9e, 0x2d, 0x12, 0xf7, 0x28, 0x18, 0x6e, 0x1b, 0x8d, 0x4c, 0x75, 0x40, 0x3e, 0xce, 0x5a,
+ 0x8c, 0x24, 0x35, 0x34, 0x13, 0xa8, 0x7b, 0x12, 0x2f, 0x3f, 0x73, 0x48, 0x4f, 0x2a, 0xf0, 0x3b,
+ 0xf5, 0xb0, 0x48, 0x39, 0x84, 0xd1, 0xc9, 0x78, 0x86, 0x78, 0xaf, 0x17, 0xf1, 0xc3, 0x08, 0x00,
+ 0x1a, 0x16, 0x10, 0x85, 0xa3, 0x35, 0x58, 0xde, 0xae, 0xd3, 0x94, 0xb0, 0x66, 0x48, 0xbb, 0x4f,
+ 0x58, 0x85, 0x55, 0x42, 0xee, 0xe3, 0x44, 0x97, 0x23, 0xb6, 0x70, 0xf6, 0xb1, 0x45, 0x1d, 0xe6,
+ 0x0e, 0x63, 0x68, 0x37, 0x90, 0x42, 0xbe, 0x1c, 0xd3, 0x6d, 0x02, 0xc7, 0x47, 0x92, 0x5e, 0xd3,
+ 0x62, 0xed, 0x3a, 0xa2, 0xdf, 0x98, 0xa6, 0x24, 0xb5, 0x17, 0x43, 0xb6, 0x6f, 0xcf, 0x70, 0x00,
+ 0xb0, 0xf2, 0x18, 0xf6, 0xec, 0x7c, 0xed, 0x64, 0x36, 0x9b, 0x3a, 0xe2, 0x84, 0x74, 0xf8, 0xfa,
+ 0x92, 0x40, 0xa0, 0xcd, 0x05, 0xc7, 0xd4, 0x80, 0x1d, 0x41, 0x03, 0xdb, 0x4d, 0x0e, 0xb7, 0x06,
+ 0x7a, 0x52, 0xf7, 0x02, 0xa2, 0xb1, 0xbe, 0x76, 0xd7, 0x26
+];
+
+ #[test]
+ fn test_tls_dhe_params() {
+ let empty = &b""[..];
+ let bytes = DHE_PARAMS;
+ let expected1 = ServerDHParams {
+ dh_p: &bytes[2..258],
+ dh_g: &bytes[260..516],
+ dh_ys: &bytes[518..774],
+ };
+ let expected2 = DigitallySigned {
+ alg: Some(SignatureAndHashAlgorithm {
+ hash: HashAlgorithm::Sha512,
+ sign: SignAlgorithm::Rsa,
+ }),
+ data: &bytes[778..],
+ };
+ let res = pair(parse_dh_params, parse_digitally_signed)(bytes);
+ assert_eq!(res, Ok((empty, (expected1, expected2))));
+ }
+} // mod tls_dh
diff --git a/rust/vendor/tls-parser/tests/tls_extensions.rs b/rust/vendor/tls-parser/tests/tls_extensions.rs
new file mode 100644
index 0000000..9a4ae56
--- /dev/null
+++ b/rust/vendor/tls-parser/tests/tls_extensions.rs
@@ -0,0 +1,209 @@
+#[macro_use]
+extern crate pretty_assertions;
+
+extern crate nom;
+extern crate tls_parser;
+
+mod tls_extensions {
+ use tls_parser::*;
+
+ #[rustfmt::skip]
+static CLIENT_EXTENSIONS1: &[u8] = &[
+ 0x00, 0x00, 0x00, 0x13, 0x00, 0x11, 0x00, 0x00, 0x0e, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01, 0x02, 0x00,
+ 0x0a, 0x00, 0x1c, 0x00, 0x1a, 0x00, 0x17, 0x00, 0x19, 0x00, 0x1c, 0x00, 0x1b, 0x00, 0x18, 0x00,
+ 0x1a, 0x00, 0x16, 0x00, 0x0e, 0x00, 0x0d, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x09, 0x00, 0x0a, 0x00,
+ 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x1e, 0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05,
+ 0x01, 0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x03,
+ 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0f, 0x00, 0x01, 0x01
+];
+
+ #[test]
+ fn test_tls_extensions() {
+ let empty = &b""[..];
+ let bytes = CLIENT_EXTENSIONS1;
+ let ec_point_formats = &[0, 1, 2];
+ let ext1 = &[0, 0, 0, 0];
+ let ecc: Vec<_> = vec![23, 25, 28, 27, 24, 26, 22, 14, 13, 11, 12, 9, 10]
+ .iter()
+ .map(|&x| NamedGroup(x))
+ .collect();
+ let expected = Ok((
+ empty,
+ vec![
+ TlsExtension::SNI(vec![(SNIType::HostName, b"www.google.com")]),
+ TlsExtension::EcPointFormats(ec_point_formats),
+ TlsExtension::EllipticCurves(ecc),
+ TlsExtension::SessionTicket(empty),
+ TlsExtension::SignatureAlgorithms(vec![
+ 0x0601, 0x0602, 0x0603, 0x0501, 0x0502, 0x0503, 0x0401, 0x0402, 0x0403, 0x0301,
+ 0x0302, 0x0303, 0x0201, 0x0202, 0x0203,
+ ]),
+ TlsExtension::StatusRequest(Some((CertificateStatusType::OCSP, ext1))),
+ TlsExtension::Heartbeat(1),
+ ],
+ ));
+
+ let res = parse_tls_extensions(bytes);
+
+ assert_eq!(res, expected);
+ }
+
+ #[test]
+ fn test_tls_extension_max_fragment_length() {
+ let empty = &b""[..];
+ let bytes = &[0x00, 0x01, 0x00, 0x01, 0x04];
+ let expected = Ok((empty, TlsExtension::MaxFragmentLength(4)));
+
+ let res = parse_tls_extension(bytes);
+
+ assert_eq!(res, expected);
+ }
+
+ #[test]
+ fn test_tls_extension_alpn() {
+ let empty = &b""[..];
+ let bytes = &[
+ 0x00, 0x10, 0x00, 0x29, 0x00, 0x27, 0x05, 0x68, 0x32, 0x2d, 0x31, 0x36, 0x05, 0x68,
+ 0x32, 0x2d, 0x31, 0x35, 0x05, 0x68, 0x32, 0x2d, 0x31, 0x34, 0x02, 0x68, 0x32, 0x08,
+ 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33, 0x2e, 0x31, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f,
+ 0x31, 0x2e, 0x31,
+ ];
+ let expected = Ok((
+ empty,
+ TlsExtension::ALPN(vec![
+ b"h2-16",
+ b"h2-15",
+ b"h2-14",
+ b"h2",
+ b"spdy/3.1",
+ b"http/1.1",
+ ]),
+ ));
+
+ let res = parse_tls_extension(bytes);
+
+ assert_eq!(res, expected);
+ }
+
+ #[test]
+ fn test_tls_extension_encrypt_then_mac() {
+ let empty = &b""[..];
+ let bytes = &[0x00, 0x16, 0x00, 0x00];
+ let expected = Ok((empty, TlsExtension::EncryptThenMac));
+
+ let res = parse_tls_extension(bytes);
+
+ assert_eq!(res, expected);
+ }
+
+ #[test]
+ fn test_tls_extension_extended_master_secret() {
+ let empty = &b""[..];
+ let bytes = &[0x00, 0x17, 0x00, 0x00];
+ let expected = Ok((empty, TlsExtension::ExtendedMasterSecret));
+
+ let res = parse_tls_extension(bytes);
+
+ assert_eq!(res, expected);
+ }
+
+ #[test]
+ fn test_tls_extension_npn() {
+ let empty = &b""[..];
+ let bytes = &[0x33, 0x74, 0x00, 0x00];
+ let expected = Ok((empty, TlsExtension::NextProtocolNegotiation));
+
+ let res = parse_tls_extension(bytes);
+
+ assert_eq!(res, expected);
+ }
+
+ #[test]
+ fn test_tls_extension_list() {
+ let empty = &b""[..];
+ let bytes = &[0, 5, 0, 0, 0, 23, 0, 0, 255, 1, 0, 1, 0];
+ let expected = Ok((
+ empty,
+ vec![
+ TlsExtension::StatusRequest(None),
+ TlsExtension::ExtendedMasterSecret,
+ TlsExtension::RenegotiationInfo(&[]),
+ ],
+ ));
+
+ let res = parse_tls_extensions(bytes);
+ println!("{:?}", res);
+
+ assert_eq!(res, expected);
+ }
+
+ #[test]
+ fn test_tls_extension_keyshare_helloretryrequest() {
+ let empty = &b""[..];
+ let bytes = &[
+ 0x00, 0x33, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0xa2, 0x4e, 0x84, 0xfa, 0x82, 0x63,
+ 0xf8, 0xff, 0x20, 0x7a, 0x79, 0x82, 0xfd, 0x34, 0x12, 0xfc, 0xae, 0x8d, 0xd8, 0xe3,
+ 0x1e, 0xf4, 0x5d, 0xe6, 0x61, 0x09, 0x3b, 0x7f, 0xa5, 0x81, 0x12, 0x63, 0x00, 0x2b,
+ 0x00, 0x02, 0x7f, 0x17,
+ ];
+ let expected = Ok((
+ empty,
+ vec![
+ TlsExtension::KeyShare(&bytes[4..40]),
+ TlsExtension::SupportedVersions(vec![TlsVersion(0x7f17)]),
+ ],
+ ));
+
+ let res = parse_tls_extensions(bytes);
+ assert_eq!(res, expected);
+ }
+
+ #[test]
+ fn test_tls_extension_signed_certificate_timestamp() {
+ let empty = &b""[..];
+ let bytes = &[0x00, 0x12, 0x00, 0x00];
+ let expected = Ok((empty, TlsExtension::SignedCertificateTimestamp(None)));
+
+ let res = parse_tls_extension(bytes);
+
+ assert_eq!(res, expected);
+ }
+
+ #[test]
+ fn test_tls_extension_grease() {
+ let empty = &b""[..];
+ let bytes = &[0x3a, 0x3a, 0x00, 0x01, 0x00];
+ let expected = TlsExtension::Grease(0x3a3a, &[0x00]);
+
+ let res = parse_tls_extension(bytes);
+
+ assert_eq!(res, Ok((empty, expected)));
+ }
+
+ const ESNI: &[u8] = include_bytes!("../assets/esni.bin");
+
+ #[test]
+ fn test_tls_extension_esni() {
+ let res = parse_tls_extension(ESNI).expect("Parsing eSNI failed");
+ match res.1 {
+ TlsExtension::EncryptedServerName {
+ ciphersuite, group, ..
+ } => {
+ assert_eq!(ciphersuite.0, 0x1301);
+ assert_eq!(group.0, 0x1d);
+ }
+ _ => panic!("Wrong extension type (expected eSNI"),
+ }
+ }
+
+ #[test]
+ fn test_tls_extension_record_size_limit() {
+ let empty = &b""[..];
+ let bytes = &[0x00, 0x1c, 0x00, 0x02, 0x40, 0x01];
+ let expected = TlsExtension::RecordSizeLimit(16385);
+ let res = parse_tls_extension(bytes);
+ assert_eq!(res, Ok((empty, expected)));
+ }
+} // mod tls_extensions
diff --git a/rust/vendor/tls-parser/tests/tls_handshake.rs b/rust/vendor/tls-parser/tests/tls_handshake.rs
new file mode 100644
index 0000000..dcd15e8
--- /dev/null
+++ b/rust/vendor/tls-parser/tests/tls_handshake.rs
@@ -0,0 +1,817 @@
+#[macro_use]
+extern crate pretty_assertions;
+
+extern crate nom;
+extern crate tls_parser;
+
+mod tls_handshake {
+ use nom::{Err, Needed};
+ use tls_parser::*;
+
+ #[rustfmt::skip]
+static CH : &[u8] = &[
+ 0x16, 0x03, 0x01, 0x01, 0x2c, 0x01, 0x00, 0x01, 0x28, 0x03, 0x03, 0xb2,
+ 0x9d, 0xd7, 0x87, 0xff, 0x21, 0xeb, 0x04, 0xc8, 0xa5, 0x38, 0x39, 0x9a,
+ 0xcf, 0xb7, 0xa3, 0x82, 0x1f, 0x82, 0x6c, 0x49, 0xbc, 0x8b, 0xb8, 0xa9,
+ 0x03, 0x0a, 0x2d, 0xce, 0x38, 0x0b, 0xf4, 0x00, 0x00, 0xaa, 0xc0, 0x30,
+ 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0xa5,
+ 0x00, 0xa3, 0x00, 0xa1, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x6a, 0x00, 0x69,
+ 0x00, 0x68, 0x00, 0x39, 0x00, 0x38, 0x00, 0x37, 0x00, 0x36, 0x00, 0x88,
+ 0x00, 0x87, 0x00, 0x86, 0x00, 0x85, 0xc0, 0x32, 0xc0, 0x2e, 0xc0, 0x2a,
+ 0xc0, 0x26, 0xc0, 0x0f, 0xc0, 0x05, 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35,
+ 0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x13,
+ 0xc0, 0x09, 0x00, 0xa4, 0x00, 0xa2, 0x00, 0xa0, 0x00, 0x9e, 0x00, 0x67,
+ 0x00, 0x40, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x33, 0x00, 0x32, 0x00, 0x31,
+ 0x00, 0x30, 0x00, 0x9a, 0x00, 0x99, 0x00, 0x98, 0x00, 0x97, 0x00, 0x45,
+ 0x00, 0x44, 0x00, 0x43, 0x00, 0x42, 0xc0, 0x31, 0xc0, 0x2d, 0xc0, 0x29,
+ 0xc0, 0x25, 0xc0, 0x0e, 0xc0, 0x04, 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f,
+ 0x00, 0x96, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0xc0, 0x0c, 0xc0, 0x02,
+ 0x00, 0x05, 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x13,
+ 0x00, 0x10, 0x00, 0x0d, 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a, 0x00, 0xff,
+ 0x01, 0x00, 0x00, 0x55, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01, 0x02,
+ 0x00, 0x0a, 0x00, 0x1c, 0x00, 0x1a, 0x00, 0x17, 0x00, 0x19, 0x00, 0x1c,
+ 0x00, 0x1b, 0x00, 0x18, 0x00, 0x1a, 0x00, 0x16, 0x00, 0x0e, 0x00, 0x0d,
+ 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x23, 0x00, 0x00,
+ 0x00, 0x0d, 0x00, 0x20, 0x00, 0x1e, 0x06, 0x01, 0x06, 0x02, 0x06, 0x03,
+ 0x05, 0x01, 0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03,
+ 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,
+ 0x00, 0x0f, 0x00, 0x01, 0x01
+];
+
+ #[test]
+ fn test_tls_record_clienthello() {
+ let empty = &b""[..];
+ let rand_data = [
+ 0xff, 0x21, 0xeb, 0x04, 0xc8, 0xa5, 0x38, 0x39, 0x9a, 0xcf, 0xb7, 0xa3, 0x82, 0x1f,
+ 0x82, 0x6c, 0x49, 0xbc, 0x8b, 0xb8, 0xa9, 0x03, 0x0a, 0x2d, 0xce, 0x38, 0x0b, 0xf4,
+ ];
+ let ciphers = vec![
+ 0xc030, 0xc02c, 0xc028, 0xc024, 0xc014, 0xc00a, 0x00a5, 0x00a3, 0x00a1, 0x009f, 0x006b,
+ 0x006a, 0x0069, 0x0068, 0x0039, 0x0038, 0x0037, 0x0036, 0x0088, 0x0087, 0x0086, 0x0085,
+ 0xc032, 0xc02e, 0xc02a, 0xc026, 0xc00f, 0xc005, 0x009d, 0x003d, 0x0035, 0x0084, 0xc02f,
+ 0xc02b, 0xc027, 0xc023, 0xc013, 0xc009, 0x00a4, 0x00a2, 0x00a0, 0x009e, 0x0067, 0x0040,
+ 0x003f, 0x003e, 0x0033, 0x0032, 0x0031, 0x0030, 0x009a, 0x0099, 0x0098, 0x0097, 0x0045,
+ 0x0044, 0x0043, 0x0042, 0xc031, 0xc02d, 0xc029, 0xc025, 0xc00e, 0xc004, 0x009c, 0x003c,
+ 0x002f, 0x0096, 0x0041, 0xc011, 0xc007, 0xc00c, 0xc002, 0x0005, 0x0004, 0xc012, 0xc008,
+ 0x0016, 0x0013, 0x0010, 0x000d, 0xc00d, 0xc003, 0x000a, 0x00ff,
+ ];
+ let comp = vec![TlsCompressionID(0x00)];
+ let expected = TlsPlaintext {
+ hdr: TlsRecordHeader {
+ record_type: TlsRecordType::Handshake,
+ version: TlsVersion::Tls10,
+ len: 300,
+ },
+ msg: vec![TlsMessage::Handshake(TlsMessageHandshake::ClientHello(
+ TlsClientHelloContents {
+ version: TlsVersion::Tls12,
+ rand_time: 0xb29d_d787,
+ rand_data: &rand_data,
+ session_id: None,
+ ciphers: ciphers.iter().map(|&x| TlsCipherSuiteID(x)).collect(),
+ comp,
+ ext: Some(&CH[220..]),
+ },
+ ))],
+ };
+ let res = parse_tls_plaintext(CH);
+ assert_eq!(res, Ok((empty, expected)));
+ }
+
+ // tls response, composed of 4 records:
+ // - Server Hello
+ // - Server Certificate
+ // - Server Key Exchange
+ // - Server Hello Done
+ #[rustfmt::skip]
+static SERVER_REPLY1: &[u8] = &[
+ 0x16, 0x03, 0x03, 0x00, 0x3b, 0x02, 0x00, 0x00, 0x37, 0x03, 0x03, 0x57,
+ 0xc4, 0x57, 0xda, 0x9c, 0xd3, 0x24, 0x6d, 0x9d, 0x02, 0x26, 0xa2, 0xe5,
+ 0x9a, 0xe8, 0xa5, 0x6f, 0x40, 0xad, 0x94, 0x30, 0xba, 0x49, 0x05, 0x3a,
+ 0x1e, 0x1b, 0xe1, 0x94, 0xa1, 0xba, 0x41, 0x00, 0xc0, 0x2f, 0x00, 0x00,
+ 0x0f, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0b,
+ 0x00, 0x02, 0x01, 0x00, 0x16, 0x03, 0x03, 0x0c, 0x09, 0x0b, 0x00, 0x0c,
+ 0x05, 0x00, 0x0c, 0x02, 0x00, 0x04, 0x84, 0x30, 0x82, 0x04, 0x80, 0x30,
+ 0x82, 0x03, 0x68, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x52, 0x1a,
+ 0x61, 0xda, 0x68, 0xb6, 0xe6, 0x35, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x49, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53,
+ 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x25, 0x30,
+ 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20,
+ 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x38, 0x31, 0x37, 0x31, 0x38,
+ 0x34, 0x39, 0x30, 0x31, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x31, 0x30,
+ 0x39, 0x31, 0x38, 0x32, 0x39, 0x30, 0x30, 0x5a, 0x30, 0x68, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61,
+ 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 0x30, 0x14,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d, 0x6f, 0x75, 0x6e, 0x74,
+ 0x61, 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x0e, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82,
+ 0x01, 0x01, 0x00, 0x9b, 0x5b, 0x36, 0xcc, 0xce, 0x8c, 0x39, 0x86, 0xbd,
+ 0x05, 0x2f, 0xc3, 0xff, 0x4c, 0x59, 0xa8, 0xfc, 0xe4, 0x6e, 0x0f, 0xc6,
+ 0xbf, 0x23, 0xf6, 0x35, 0xc5, 0x3b, 0xcc, 0xc9, 0x61, 0x2f, 0x60, 0x11,
+ 0x9b, 0x7a, 0x44, 0xd2, 0xd0, 0xd9, 0x62, 0x11, 0x09, 0xbe, 0x08, 0x53,
+ 0x24, 0x73, 0xd9, 0x5f, 0x5e, 0xb0, 0x6f, 0x05, 0x3f, 0x53, 0xa3, 0x2d,
+ 0x98, 0xa4, 0xf4, 0xaf, 0x23, 0x25, 0xb8, 0x80, 0xbc, 0xcc, 0xde, 0xa2,
+ 0x56, 0xcb, 0x6f, 0x9d, 0x1a, 0xda, 0xa5, 0xbe, 0xb0, 0x8a, 0xdc, 0xcf,
+ 0x30, 0xef, 0xe0, 0x68, 0x97, 0xc5, 0x70, 0xad, 0xcf, 0x10, 0x5b, 0xb6,
+ 0x92, 0x98, 0x61, 0x57, 0x3d, 0xbf, 0x3f, 0xd0, 0x5d, 0xbc, 0x76, 0x23,
+ 0xc8, 0xce, 0x35, 0x6d, 0x25, 0x1f, 0x11, 0x5a, 0x4b, 0x76, 0x36, 0xca,
+ 0xd4, 0x57, 0x7e, 0x95, 0x7f, 0x78, 0xfb, 0x2c, 0xe0, 0x9a, 0xbf, 0x64,
+ 0xc6, 0x43, 0x7b, 0xcd, 0xfa, 0x0e, 0xaa, 0x4f, 0x6a, 0xda, 0x04, 0xa4,
+ 0xf5, 0xfa, 0x2d, 0xea, 0xac, 0xc3, 0xa7, 0xf4, 0xd3, 0x7c, 0x57, 0xd4,
+ 0xb8, 0x2c, 0xcb, 0xe0, 0xd5, 0x26, 0x3b, 0x2d, 0x64, 0x0d, 0x20, 0x5a,
+ 0xd5, 0xe4, 0x1a, 0x6e, 0x3a, 0x6a, 0x23, 0xb1, 0x0a, 0xc6, 0x33, 0xee,
+ 0x49, 0x66, 0x13, 0x38, 0x58, 0x76, 0x53, 0x84, 0x4a, 0x8a, 0xaa, 0x77,
+ 0x8e, 0xa8, 0x38, 0xfb, 0xe9, 0x4d, 0xd0, 0x02, 0xf9, 0x7b, 0xf3, 0x67,
+ 0x94, 0xe0, 0x58, 0x9e, 0x04, 0xc1, 0x3b, 0xd8, 0x2b, 0x89, 0x5f, 0x57,
+ 0xf3, 0xb5, 0xf3, 0x41, 0x63, 0x7a, 0x32, 0x98, 0x5e, 0x18, 0x29, 0x04,
+ 0xb7, 0x64, 0xbe, 0x91, 0xf9, 0x15, 0xf7, 0x34, 0x23, 0x0f, 0x4d, 0xd1,
+ 0xeb, 0x80, 0xe9, 0xad, 0xb3, 0x65, 0xc1, 0xcd, 0x7e, 0x68, 0x3f, 0x9b,
+ 0x0c, 0x6d, 0xb2, 0xbf, 0x16, 0x11, 0x21, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0xa3, 0x82, 0x01, 0x4b, 0x30, 0x82, 0x01, 0x47, 0x30, 0x1d, 0x06, 0x03,
+ 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01,
+ 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x03, 0x02, 0x30, 0x19, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x12,
+ 0x30, 0x10, 0x82, 0x0e, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x68, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x5c, 0x30, 0x5a, 0x30, 0x2b,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x1f,
+ 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x47, 0x49,
+ 0x41, 0x47, 0x32, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x2b, 0x06, 0x08, 0x2b,
+ 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x1f, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x31,
+ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
+ 0x6f, 0x63, 0x73, 0x70, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04,
+ 0x16, 0x04, 0x14, 0x2e, 0x67, 0x92, 0x22, 0x0f, 0xd3, 0xd5, 0xd1, 0xd6,
+ 0x0a, 0x21, 0xf5, 0x3e, 0x2b, 0xe7, 0x87, 0xbe, 0xaf, 0x37, 0x9b, 0x30,
+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30,
+ 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
+ 0x80, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b, 0xbc, 0xf6, 0x68, 0xb5, 0x76,
+ 0xf5, 0x81, 0xb6, 0xbb, 0x62, 0x1a, 0xba, 0x5a, 0x81, 0x2f, 0x30, 0x21,
+ 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x1a, 0x30, 0x18, 0x30, 0x0c, 0x06,
+ 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01, 0x30,
+ 0x08, 0x06, 0x06, 0x67, 0x81, 0x0c, 0x01, 0x02, 0x02, 0x30, 0x30, 0x06,
+ 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x29, 0x30, 0x27, 0x30, 0x25, 0xa0, 0x23,
+ 0xa0, 0x21, 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70,
+ 0x6b, 0x69, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32, 0x2e, 0x63, 0x72, 0x6c, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+ 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x7d, 0x0e, 0x9e, 0x7b, 0xf0,
+ 0x81, 0xd6, 0x19, 0xa5, 0xc1, 0xe3, 0xd4, 0x16, 0xad, 0x17, 0x74, 0x76,
+ 0x80, 0x97, 0x9c, 0x96, 0x7b, 0xfb, 0x8e, 0x3a, 0x12, 0x14, 0x25, 0x48,
+ 0xb9, 0xed, 0x46, 0xc9, 0x07, 0xc6, 0xd9, 0xfd, 0x06, 0xba, 0x9f, 0x66,
+ 0xd6, 0x1c, 0xe4, 0xbb, 0xcb, 0x76, 0x44, 0x95, 0x31, 0x76, 0x4c, 0xfb,
+ 0xb5, 0xad, 0xc7, 0xf0, 0x6a, 0xfa, 0x30, 0xc3, 0x58, 0xa1, 0x8b, 0xcc,
+ 0xe2, 0x70, 0xbb, 0x8a, 0x78, 0x5e, 0x41, 0x60, 0x1e, 0xda, 0x69, 0xc3,
+ 0xcb, 0x9f, 0xa2, 0x10, 0xff, 0x20, 0xfc, 0xa4, 0x35, 0xdb, 0x32, 0xcb,
+ 0x26, 0xba, 0xc0, 0xcf, 0x3f, 0x5c, 0x86, 0x78, 0x2c, 0xaa, 0x73, 0x39,
+ 0xf9, 0x8c, 0xfd, 0xa6, 0x9a, 0x8e, 0x3f, 0x5d, 0x7d, 0x8c, 0x7c, 0x3a,
+ 0xe7, 0xbe, 0x69, 0x73, 0xa8, 0x06, 0x5d, 0x56, 0xe3, 0xe2, 0x80, 0x0d,
+ 0x99, 0xcc, 0x4d, 0x5f, 0x7e, 0xfb, 0x62, 0xd8, 0xcf, 0x55, 0x2d, 0xbc,
+ 0x9f, 0xef, 0xa7, 0xe6, 0x46, 0xda, 0xc9, 0x66, 0x07, 0x0e, 0x13, 0x4d,
+ 0x61, 0xb3, 0x85, 0xf3, 0x72, 0x6d, 0x41, 0xfe, 0x7b, 0xaa, 0xe7, 0xaf,
+ 0xff, 0x61, 0xd9, 0xc6, 0x6c, 0x84, 0x6c, 0x1a, 0x9e, 0xda, 0x86, 0x15,
+ 0xbc, 0x2a, 0xae, 0x84, 0x14, 0x94, 0x67, 0x95, 0xc4, 0xda, 0x35, 0x29,
+ 0x8e, 0x80, 0x23, 0xc0, 0x4a, 0xdd, 0x0e, 0xb3, 0xb1, 0x7d, 0xc7, 0x3d,
+ 0xea, 0x2c, 0x41, 0xb2, 0xed, 0xb4, 0x8b, 0x65, 0xd3, 0x62, 0x81, 0x0a,
+ 0x25, 0x0c, 0x3b, 0xc9, 0x11, 0xa2, 0x50, 0x1f, 0xd0, 0xe9, 0x37, 0x9f,
+ 0xa0, 0x7a, 0x34, 0x01, 0xdf, 0x32, 0x58, 0x3b, 0xf5, 0x4b, 0xd8, 0xab,
+ 0x11, 0x5a, 0x9a, 0x1b, 0x83, 0x43, 0x06, 0xf4, 0x40, 0x1e, 0x5b, 0x92,
+ 0xe8, 0x94, 0x0a, 0xbc, 0x57, 0x2f, 0x19, 0x69, 0xc6, 0xd2, 0x8b, 0x00,
+ 0x03, 0xf4, 0x30, 0x82, 0x03, 0xf0, 0x30, 0x82, 0x02, 0xd8, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x03, 0x02, 0x3a, 0x92, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30,
+ 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x0d, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x49, 0x6e,
+ 0x63, 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+ 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6c,
+ 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31,
+ 0x35, 0x30, 0x34, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
+ 0x17, 0x0d, 0x31, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39,
+ 0x35, 0x39, 0x5a, 0x30, 0x49, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20,
+ 0x49, 0x6e, 0x63, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74,
+ 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
+ 0x69, 0x74, 0x79, 0x20, 0x47, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82,
+ 0x01, 0x01, 0x00, 0x9c, 0x2a, 0x04, 0x77, 0x5c, 0xd8, 0x50, 0x91, 0x3a,
+ 0x06, 0xa3, 0x82, 0xe0, 0xd8, 0x50, 0x48, 0xbc, 0x89, 0x3f, 0xf1, 0x19,
+ 0x70, 0x1a, 0x88, 0x46, 0x7e, 0xe0, 0x8f, 0xc5, 0xf1, 0x89, 0xce, 0x21,
+ 0xee, 0x5a, 0xfe, 0x61, 0x0d, 0xb7, 0x32, 0x44, 0x89, 0xa0, 0x74, 0x0b,
+ 0x53, 0x4f, 0x55, 0xa4, 0xce, 0x82, 0x62, 0x95, 0xee, 0xeb, 0x59, 0x5f,
+ 0xc6, 0xe1, 0x05, 0x80, 0x12, 0xc4, 0x5e, 0x94, 0x3f, 0xbc, 0x5b, 0x48,
+ 0x38, 0xf4, 0x53, 0xf7, 0x24, 0xe6, 0xfb, 0x91, 0xe9, 0x15, 0xc4, 0xcf,
+ 0xf4, 0x53, 0x0d, 0xf4, 0x4a, 0xfc, 0x9f, 0x54, 0xde, 0x7d, 0xbe, 0xa0,
+ 0x6b, 0x6f, 0x87, 0xc0, 0xd0, 0x50, 0x1f, 0x28, 0x30, 0x03, 0x40, 0xda,
+ 0x08, 0x73, 0x51, 0x6c, 0x7f, 0xff, 0x3a, 0x3c, 0xa7, 0x37, 0x06, 0x8e,
+ 0xbd, 0x4b, 0x11, 0x04, 0xeb, 0x7d, 0x24, 0xde, 0xe6, 0xf9, 0xfc, 0x31,
+ 0x71, 0xfb, 0x94, 0xd5, 0x60, 0xf3, 0x2e, 0x4a, 0xaf, 0x42, 0xd2, 0xcb,
+ 0xea, 0xc4, 0x6a, 0x1a, 0xb2, 0xcc, 0x53, 0xdd, 0x15, 0x4b, 0x8b, 0x1f,
+ 0xc8, 0x19, 0x61, 0x1f, 0xcd, 0x9d, 0xa8, 0x3e, 0x63, 0x2b, 0x84, 0x35,
+ 0x69, 0x65, 0x84, 0xc8, 0x19, 0xc5, 0x46, 0x22, 0xf8, 0x53, 0x95, 0xbe,
+ 0xe3, 0x80, 0x4a, 0x10, 0xc6, 0x2a, 0xec, 0xba, 0x97, 0x20, 0x11, 0xc7,
+ 0x39, 0x99, 0x10, 0x04, 0xa0, 0xf0, 0x61, 0x7a, 0x95, 0x25, 0x8c, 0x4e,
+ 0x52, 0x75, 0xe2, 0xb6, 0xed, 0x08, 0xca, 0x14, 0xfc, 0xce, 0x22, 0x6a,
+ 0xb3, 0x4e, 0xcf, 0x46, 0x03, 0x97, 0x97, 0x03, 0x7e, 0xc0, 0xb1, 0xde,
+ 0x7b, 0xaf, 0x45, 0x33, 0xcf, 0xba, 0x3e, 0x71, 0xb7, 0xde, 0xf4, 0x25,
+ 0x25, 0xc2, 0x0d, 0x35, 0x89, 0x9d, 0x9d, 0xfb, 0x0e, 0x11, 0x79, 0x89,
+ 0x1e, 0x37, 0xc5, 0xaf, 0x8e, 0x72, 0x69, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0xa3, 0x81, 0xe7, 0x30, 0x81, 0xe4, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d,
+ 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xc0, 0x7a, 0x98, 0x68, 0x8d,
+ 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c, 0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8,
+ 0xca, 0xcc, 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
+ 0x04, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b, 0xbc, 0xf6, 0x68, 0xb5, 0x76,
+ 0xf5, 0x81, 0xb6, 0xbb, 0x62, 0x1a, 0xba, 0x5a, 0x81, 0x2f, 0x30, 0x0e,
+ 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02,
+ 0x01, 0x06, 0x30, 0x2e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x01, 0x01, 0x04, 0x22, 0x30, 0x20, 0x30, 0x1e, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x12, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x67, 0x2e, 0x73, 0x79, 0x6d, 0x63, 0x64, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
+ 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x35,
+ 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2e, 0x30, 0x2c, 0x30, 0x2a, 0xa0,
+ 0x28, 0xa0, 0x26, 0x86, 0x24, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+ 0x67, 0x2e, 0x73, 0x79, 0x6d, 0x63, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
+ 0x63, 0x72, 0x6c, 0x73, 0x2f, 0x67, 0x74, 0x67, 0x6c, 0x6f, 0x62, 0x61,
+ 0x6c, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x17, 0x06, 0x03, 0x55, 0x1d, 0x20,
+ 0x04, 0x10, 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
+ 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01,
+ 0x01, 0x00, 0x08, 0x4e, 0x04, 0xa7, 0x80, 0x7f, 0x10, 0x16, 0x43, 0x5e,
+ 0x02, 0xad, 0xd7, 0x42, 0x80, 0xf4, 0xb0, 0x8e, 0xd2, 0xae, 0xb3, 0xeb,
+ 0x11, 0x7d, 0x90, 0x84, 0x18, 0x7d, 0xe7, 0x90, 0x15, 0xfb, 0x49, 0x7f,
+ 0xa8, 0x99, 0x05, 0x91, 0xbb, 0x7a, 0xc9, 0xd6, 0x3c, 0x37, 0x18, 0x09,
+ 0x9a, 0xb6, 0xc7, 0x92, 0x20, 0x07, 0x35, 0x33, 0x09, 0xe4, 0x28, 0x63,
+ 0x72, 0x0d, 0xb4, 0xe0, 0x32, 0x9c, 0x87, 0x98, 0xc4, 0x1b, 0x76, 0x89,
+ 0x67, 0xc1, 0x50, 0x58, 0xb0, 0x13, 0xaa, 0x13, 0x1a, 0x1b, 0x32, 0xa5,
+ 0xbe, 0xea, 0x11, 0x95, 0x4c, 0x48, 0x63, 0x49, 0xe9, 0x99, 0x5d, 0x20,
+ 0x37, 0xcc, 0xfe, 0x2a, 0x69, 0x51, 0x16, 0x95, 0x4b, 0xa9, 0xde, 0x49,
+ 0x82, 0xc0, 0x10, 0x70, 0xf4, 0x2c, 0xf3, 0xec, 0xbc, 0x24, 0x24, 0xd0,
+ 0x4e, 0xac, 0xa5, 0xd9, 0x5e, 0x1e, 0x6d, 0x92, 0xc1, 0xa7, 0xac, 0x48,
+ 0x35, 0x81, 0xf9, 0xe5, 0xe4, 0x9c, 0x65, 0x69, 0xcd, 0x87, 0xa4, 0x41,
+ 0x50, 0x3f, 0x2e, 0x57, 0xa5, 0x91, 0x51, 0x12, 0x58, 0x0e, 0x8c, 0x09,
+ 0xa1, 0xac, 0x7a, 0xa4, 0x12, 0xa5, 0x27, 0xf3, 0x9a, 0x10, 0x97, 0x7d,
+ 0x55, 0x03, 0x06, 0xf7, 0x66, 0x58, 0x5f, 0x5f, 0x64, 0xe1, 0xab, 0x5d,
+ 0x6d, 0xa5, 0x39, 0x48, 0x75, 0x98, 0x4c, 0x29, 0x5a, 0x3a, 0x8d, 0xd3,
+ 0x2b, 0xca, 0x9c, 0x55, 0x04, 0xbf, 0xf4, 0xe6, 0x14, 0xd5, 0x80, 0xac,
+ 0x26, 0xed, 0x17, 0x89, 0xa6, 0x93, 0x6c, 0x5c, 0xa4, 0xcc, 0xb8, 0xf0,
+ 0x66, 0x8e, 0x64, 0xe3, 0x7d, 0x9a, 0xe2, 0x00, 0xb3, 0x49, 0xc7, 0xe4,
+ 0x0a, 0xaa, 0xdd, 0x5b, 0x83, 0xc7, 0x70, 0x90, 0x46, 0x4e, 0xbe, 0xd0,
+ 0xdb, 0x59, 0x96, 0x6c, 0x2e, 0xf5, 0x16, 0x36, 0xde, 0x71, 0xcc, 0x01,
+ 0xc2, 0x12, 0xc1, 0x21, 0xc6, 0x16, 0x00, 0x03, 0x81, 0x30, 0x82, 0x03,
+ 0x7d, 0x30, 0x82, 0x02, 0xe6, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03,
+ 0x12, 0xbb, 0xe6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x4e, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30,
+ 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, 0x45, 0x71, 0x75, 0x69,
+ 0x66, 0x61, 0x78, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 0x0b,
+ 0x13, 0x24, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53, 0x65,
+ 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
+ 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
+ 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x32, 0x30, 0x35, 0x32, 0x31,
+ 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x38, 0x30,
+ 0x38, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x42,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+ 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d,
+ 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x49, 0x6e, 0x63,
+ 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12,
+ 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f,
+ 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82,
+ 0x01, 0x01, 0x00, 0xda, 0xcc, 0x18, 0x63, 0x30, 0xfd, 0xf4, 0x17, 0x23,
+ 0x1a, 0x56, 0x7e, 0x5b, 0xdf, 0x3c, 0x6c, 0x38, 0xe4, 0x71, 0xb7, 0x78,
+ 0x91, 0xd4, 0xbc, 0xa1, 0xd8, 0x4c, 0xf8, 0xa8, 0x43, 0xb6, 0x03, 0xe9,
+ 0x4d, 0x21, 0x07, 0x08, 0x88, 0xda, 0x58, 0x2f, 0x66, 0x39, 0x29, 0xbd,
+ 0x05, 0x78, 0x8b, 0x9d, 0x38, 0xe8, 0x05, 0xb7, 0x6a, 0x7e, 0x71, 0xa4,
+ 0xe6, 0xc4, 0x60, 0xa6, 0xb0, 0xef, 0x80, 0xe4, 0x89, 0x28, 0x0f, 0x9e,
+ 0x25, 0xd6, 0xed, 0x83, 0xf3, 0xad, 0xa6, 0x91, 0xc7, 0x98, 0xc9, 0x42,
+ 0x18, 0x35, 0x14, 0x9d, 0xad, 0x98, 0x46, 0x92, 0x2e, 0x4f, 0xca, 0xf1,
+ 0x87, 0x43, 0xc1, 0x16, 0x95, 0x57, 0x2d, 0x50, 0xef, 0x89, 0x2d, 0x80,
+ 0x7a, 0x57, 0xad, 0xf2, 0xee, 0x5f, 0x6b, 0xd2, 0x00, 0x8d, 0xb9, 0x14,
+ 0xf8, 0x14, 0x15, 0x35, 0xd9, 0xc0, 0x46, 0xa3, 0x7b, 0x72, 0xc8, 0x91,
+ 0xbf, 0xc9, 0x55, 0x2b, 0xcd, 0xd0, 0x97, 0x3e, 0x9c, 0x26, 0x64, 0xcc,
+ 0xdf, 0xce, 0x83, 0x19, 0x71, 0xca, 0x4e, 0xe6, 0xd4, 0xd5, 0x7b, 0xa9,
+ 0x19, 0xcd, 0x55, 0xde, 0xc8, 0xec, 0xd2, 0x5e, 0x38, 0x53, 0xe5, 0x5c,
+ 0x4f, 0x8c, 0x2d, 0xfe, 0x50, 0x23, 0x36, 0xfc, 0x66, 0xe6, 0xcb, 0x8e,
+ 0xa4, 0x39, 0x19, 0x00, 0xb7, 0x95, 0x02, 0x39, 0x91, 0x0b, 0x0e, 0xfe,
+ 0x38, 0x2e, 0xd1, 0x1d, 0x05, 0x9a, 0xf6, 0x4d, 0x3e, 0x6f, 0x0f, 0x07,
+ 0x1d, 0xaf, 0x2c, 0x1e, 0x8f, 0x60, 0x39, 0xe2, 0xfa, 0x36, 0x53, 0x13,
+ 0x39, 0xd4, 0x5e, 0x26, 0x2b, 0xdb, 0x3d, 0xa8, 0x14, 0xbd, 0x32, 0xeb,
+ 0x18, 0x03, 0x28, 0x52, 0x04, 0x71, 0xe5, 0xab, 0x33, 0x3d, 0xe1, 0x38,
+ 0xbb, 0x07, 0x36, 0x84, 0x62, 0x9c, 0x79, 0xea, 0x16, 0x30, 0xf4, 0x5f,
+ 0xc0, 0x2b, 0xe8, 0x71, 0x6b, 0xe4, 0xf9, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0xa3, 0x81, 0xf0, 0x30, 0x81, 0xed, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d,
+ 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x48, 0xe6, 0x68, 0xf9, 0x2b,
+ 0xd2, 0xb2, 0x95, 0xd7, 0x47, 0xd8, 0x23, 0x20, 0x10, 0x4f, 0x33, 0x98,
+ 0x90, 0x9f, 0xd4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
+ 0x04, 0x14, 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64,
+ 0x0c, 0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e, 0x30, 0x0f,
+ 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03,
+ 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
+ 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x3a, 0x06, 0x03, 0x55,
+ 0x1d, 0x1f, 0x04, 0x33, 0x30, 0x31, 0x30, 0x2f, 0xa0, 0x2d, 0xa0, 0x2b,
+ 0x86, 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c,
+ 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x2f, 0x63, 0x72, 0x6c, 0x73, 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72,
+ 0x65, 0x63, 0x61, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x4e, 0x06, 0x03, 0x55,
+ 0x1d, 0x20, 0x04, 0x47, 0x30, 0x45, 0x30, 0x43, 0x06, 0x04, 0x55, 0x1d,
+ 0x20, 0x00, 0x30, 0x3b, 0x30, 0x39, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x02, 0x01, 0x16, 0x2d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a,
+ 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75,
+ 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x73, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
+ 0x6f, 0x72, 0x79, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x76, 0xe1,
+ 0x12, 0x6e, 0x4e, 0x4b, 0x16, 0x12, 0x86, 0x30, 0x06, 0xb2, 0x81, 0x08,
+ 0xcf, 0xf0, 0x08, 0xc7, 0xc7, 0x71, 0x7e, 0x66, 0xee, 0xc2, 0xed, 0xd4,
+ 0x3b, 0x1f, 0xff, 0xf0, 0xf0, 0xc8, 0x4e, 0xd6, 0x43, 0x38, 0xb0, 0xb9,
+ 0x30, 0x7d, 0x18, 0xd0, 0x55, 0x83, 0xa2, 0x6a, 0xcb, 0x36, 0x11, 0x9c,
+ 0xe8, 0x48, 0x66, 0xa3, 0x6d, 0x7f, 0xb8, 0x13, 0xd4, 0x47, 0xfe, 0x8b,
+ 0x5a, 0x5c, 0x73, 0xfc, 0xae, 0xd9, 0x1b, 0x32, 0x19, 0x38, 0xab, 0x97,
+ 0x34, 0x14, 0xaa, 0x96, 0xd2, 0xeb, 0xa3, 0x1c, 0x14, 0x08, 0x49, 0xb6,
+ 0xbb, 0xe5, 0x91, 0xef, 0x83, 0x36, 0xeb, 0x1d, 0x56, 0x6f, 0xca, 0xda,
+ 0xbc, 0x73, 0x63, 0x90, 0xe4, 0x7f, 0x7b, 0x3e, 0x22, 0xcb, 0x3d, 0x07,
+ 0xed, 0x5f, 0x38, 0x74, 0x9c, 0xe3, 0x03, 0x50, 0x4e, 0xa1, 0xaf, 0x98,
+ 0xee, 0x61, 0xf2, 0x84, 0x3f, 0x12, 0x16, 0x03, 0x03, 0x01, 0x4d, 0x0c,
+ 0x00, 0x01, 0x49, 0x03, 0x00, 0x17, 0x41, 0x04, 0x27, 0x7e, 0x6c, 0x81,
+ 0xf1, 0xb4, 0xb5, 0x60, 0x22, 0x45, 0x9b, 0x26, 0x4f, 0xb8, 0xa8, 0xbd,
+ 0xd2, 0x91, 0x88, 0x9b, 0xe0, 0xe8, 0x41, 0x4d, 0x7c, 0xab, 0xcf, 0xf7,
+ 0x3f, 0x8f, 0x23, 0xd1, 0x18, 0xdd, 0xb7, 0x27, 0xbd, 0xcf, 0xd3, 0x14,
+ 0x71, 0xca, 0xf9, 0x7e, 0xb8, 0xe8, 0x15, 0x59, 0xa2, 0x97, 0x66, 0x27,
+ 0x45, 0xc3, 0x40, 0xf7, 0xa8, 0x77, 0x61, 0x05, 0x9b, 0xb2, 0xa9, 0xd0,
+ 0x06, 0x01, 0x01, 0x00, 0x6e, 0xd0, 0x13, 0x15, 0x52, 0x29, 0xdb, 0x2c,
+ 0x60, 0x3c, 0x2d, 0xf3, 0x6f, 0xc5, 0xac, 0x44, 0x53, 0x47, 0x3b, 0x17,
+ 0xbc, 0xaf, 0xaa, 0x9f, 0x5d, 0xf5, 0x2e, 0x7a, 0x9c, 0x32, 0x58, 0xb5,
+ 0x37, 0x1a, 0xce, 0x4c, 0x12, 0x9e, 0x47, 0xf0, 0xfd, 0x85, 0x38, 0x39,
+ 0xc1, 0xec, 0xd8, 0x06, 0xc8, 0x84, 0x87, 0x03, 0xfa, 0x41, 0xf9, 0x88,
+ 0xa0, 0xef, 0x84, 0x87, 0x76, 0x6e, 0x61, 0xfc, 0x1c, 0x78, 0xd8, 0x70,
+ 0xa8, 0x65, 0x3a, 0x1e, 0x84, 0xac, 0x14, 0x78, 0x74, 0x18, 0x7f, 0xdd,
+ 0x35, 0x2e, 0x99, 0xd8, 0x3d, 0x68, 0x66, 0x16, 0x7a, 0x83, 0x16, 0xa6,
+ 0x21, 0x18, 0x71, 0x6f, 0x58, 0x32, 0x60, 0xa3, 0x70, 0xa6, 0xca, 0x04,
+ 0xd5, 0x09, 0xbe, 0xc3, 0x32, 0xc9, 0xee, 0x5d, 0x9a, 0x56, 0xdb, 0xf6,
+ 0x17, 0xf1, 0x2c, 0x6d, 0x71, 0x4f, 0xf7, 0x8a, 0x2a, 0xa3, 0xcf, 0xb9,
+ 0x86, 0x0a, 0xc2, 0xfd, 0x75, 0xab, 0xb2, 0x75, 0x39, 0xb5, 0xf5, 0x2b,
+ 0xb2, 0x80, 0x9e, 0x9b, 0x32, 0x26, 0x25, 0x6c, 0x0e, 0x71, 0xdf, 0xc0,
+ 0x42, 0x4e, 0x74, 0xd8, 0xb0, 0x9b, 0xa5, 0x15, 0xe5, 0x96, 0xd7, 0x30,
+ 0xdf, 0x33, 0x3d, 0xfd, 0xba, 0xf7, 0x59, 0x7d, 0xdb, 0xc9, 0x31, 0x3d,
+ 0x70, 0xe4, 0xd4, 0x91, 0x97, 0x70, 0x2d, 0xf2, 0x48, 0xcd, 0x84, 0x2d,
+ 0x70, 0x48, 0xbc, 0xd6, 0x6b, 0xaf, 0xdd, 0xf6, 0x7d, 0xad, 0xb9, 0x89,
+ 0x94, 0x7c, 0x59, 0x0c, 0x3f, 0x3e, 0xe2, 0x8d, 0x4c, 0x81, 0x4a, 0x15,
+ 0x09, 0xb9, 0xde, 0xc1, 0xe6, 0xe6, 0x5d, 0x28, 0x2d, 0x1d, 0xb8, 0x45,
+ 0x17, 0x42, 0x55, 0xe3, 0x2a, 0xcf, 0x55, 0x26, 0x66, 0x79, 0xf1, 0xbb,
+ 0x2a, 0x25, 0x28, 0x78, 0xa1, 0x63, 0x90, 0xec, 0xec, 0xa7, 0xee, 0x61,
+ 0x1c, 0xac, 0x19, 0x45, 0xdd, 0x82, 0xae, 0x52, 0x16, 0x03, 0x03, 0x00,
+ 0x04, 0x0e, 0x00, 0x00, 0x00
+];
+
+ #[test]
+ fn test_tls_record_serverhello() {
+ let empty = &b""[..];
+ let bytes = &SERVER_REPLY1[0..64];
+ let expected = TlsPlaintext {
+ hdr: TlsRecordHeader {
+ record_type: TlsRecordType::Handshake,
+ version: TlsVersion::Tls12,
+ len: 59,
+ },
+ msg: vec![TlsMessage::Handshake(TlsMessageHandshake::ServerHello(
+ TlsServerHelloContents {
+ version: TlsVersion::Tls12,
+ rand_time: 0x57c4_57da,
+ rand_data: &bytes[15..43],
+ session_id: None,
+ cipher: TlsCipherSuiteID(0xc02f),
+ compression: TlsCompressionID(0),
+ ext: Some(&bytes[49..]),
+ },
+ ))],
+ };
+ assert_eq!(parse_tls_plaintext(bytes), Ok((empty, expected)));
+ }
+
+ #[test]
+ fn test_tls_record_certificate() {
+ let empty = &b""[..];
+ let bytes = &SERVER_REPLY1[64..3150];
+ let chain = vec![
+ RawCertificate {
+ data: &bytes[15..1171],
+ },
+ RawCertificate {
+ data: &bytes[1174..2186],
+ },
+ RawCertificate {
+ data: &bytes[2189..3086],
+ },
+ ];
+ for cert in &chain {
+ println!("cert len: {}", cert.data.len());
+ }
+ let expected = TlsPlaintext {
+ hdr: TlsRecordHeader {
+ record_type: TlsRecordType::Handshake,
+ version: TlsVersion::Tls12,
+ len: 3081,
+ },
+ msg: vec![TlsMessage::Handshake(TlsMessageHandshake::Certificate(
+ TlsCertificateContents { cert_chain: chain },
+ ))],
+ };
+ assert_eq!(parse_tls_plaintext(bytes), Ok((empty, expected)));
+ }
+
+ #[test]
+ fn test_tls_record_serverkeyexchange() {
+ let empty = &b""[..];
+ let bytes = &SERVER_REPLY1[3150..3488];
+ let expected = TlsPlaintext {
+ hdr: TlsRecordHeader {
+ record_type: TlsRecordType::Handshake,
+ version: TlsVersion::Tls12,
+ len: 333,
+ },
+ msg: vec![TlsMessage::Handshake(
+ TlsMessageHandshake::ServerKeyExchange(TlsServerKeyExchangeContents {
+ parameters: &bytes[9..],
+ }),
+ )],
+ };
+ assert_eq!(parse_tls_plaintext(bytes), Ok((empty, expected)));
+ }
+
+ #[test]
+ fn test_tls_record_serverdone() {
+ let empty = &b""[..];
+ let bytes = &SERVER_REPLY1[3488..];
+ let expected = TlsPlaintext {
+ hdr: TlsRecordHeader {
+ record_type: TlsRecordType::Handshake,
+ version: TlsVersion::Tls12,
+ len: 4,
+ },
+ msg: vec![TlsMessage::Handshake(TlsMessageHandshake::ServerDone(
+ empty,
+ ))],
+ };
+ assert_eq!(parse_tls_plaintext(bytes), Ok((empty, expected)));
+ }
+
+ // client response, composed of 3 records:
+ // - Client Key Exchange
+ // - Change Cipher Spec
+ // - an encrypted handshake message
+ #[rustfmt::skip]
+static CLIENT_REPLY1: &[u8] = &[
+ 0x16, 0x03, 0x03, 0x00, 0x46, 0x10, 0x00, 0x00, 0x42, 0x41, 0x04, 0x22,
+ 0xd3, 0xf9, 0xbf, 0xbb, 0x7e, 0x34, 0xf9, 0x95, 0x68, 0x2e, 0xe2, 0xf8,
+ 0xf3, 0xf8, 0x08, 0x9c, 0x78, 0x32, 0x81, 0xa8, 0x28, 0x33, 0x5e, 0x46,
+ 0x11, 0xf2, 0x31, 0x2c, 0x9f, 0x77, 0xda, 0xc0, 0x88, 0xb5, 0xb4, 0x19,
+ 0xc0, 0x97, 0x3d, 0xe0, 0x99, 0x5c, 0xec, 0x1e, 0xbc, 0x32, 0x62, 0x8e,
+ 0x47, 0xc4, 0x7c, 0xcb, 0x31, 0x38, 0x5a, 0xed, 0x09, 0x1f, 0x82, 0xb1,
+ 0xb3, 0xce, 0x43, 0x14, 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03, 0x03,
+ 0x00, 0x28, 0x00, 0x74, 0x47, 0x18, 0x4c, 0x5f, 0xbf, 0x65, 0xfe, 0xb9,
+ 0x34, 0xcf, 0x21, 0x8d, 0x6c, 0xd6, 0x99, 0xac, 0x24, 0xd3, 0x5a, 0x54,
+ 0x44, 0x05, 0x41, 0x7b, 0x1a, 0x25, 0xe6, 0xbf, 0xe0, 0x82, 0x95, 0x72,
+ 0x38, 0x7a, 0xa5, 0xd8, 0xf3, 0x72
+];
+
+ #[test]
+ fn test_tls_record_clientkeyexchange() {
+ let empty = &b""[..];
+ let bytes = &CLIENT_REPLY1[0..75];
+ let expected = TlsPlaintext {
+ hdr: TlsRecordHeader {
+ record_type: TlsRecordType::Handshake,
+ version: TlsVersion::Tls12,
+ len: 70,
+ },
+ msg: vec![TlsMessage::Handshake(
+ TlsMessageHandshake::ClientKeyExchange(TlsClientKeyExchangeContents::Unknown(
+ &bytes[9..],
+ )),
+ )],
+ };
+ assert_eq!(parse_tls_plaintext(bytes), Ok((empty, expected)));
+ }
+
+ #[test]
+ fn test_tls_record_changecipherspec() {
+ let empty = &b""[..];
+ let bytes = &CLIENT_REPLY1[75..81];
+ let expected = TlsPlaintext {
+ hdr: TlsRecordHeader {
+ record_type: TlsRecordType::ChangeCipherSpec,
+ version: TlsVersion::Tls12,
+ len: 1,
+ },
+ msg: vec![TlsMessage::ChangeCipherSpec],
+ };
+ assert_eq!(parse_tls_plaintext(bytes), Ok((empty, expected)));
+ }
+
+ #[test]
+ fn test_tls_record_encryptedhandshake() {
+ let empty = &b""[..];
+ let bytes = &CLIENT_REPLY1[81..];
+ let expected = TlsEncrypted {
+ hdr: TlsRecordHeader {
+ record_type: TlsRecordType::Handshake,
+ version: TlsVersion::Tls12,
+ len: bytes.len() as u16 - 5,
+ },
+ msg: TlsEncryptedContent { blob: &bytes[5..] },
+ };
+ assert_eq!(parse_tls_encrypted(bytes), Ok((empty, expected)));
+ }
+
+ #[rustfmt::skip]
+static SERVER_HELLO1: &[u8] = &[
+ 0x16, 0x03, 0x03, 0x00, 0x3b, 0x02, 0x00, 0x00, 0x37, 0x03, 0x03, 0x57,
+ 0xc4, 0x57, 0xda, 0x9c, 0xd3, 0x24, 0x6d, 0x9d, 0x02, 0x26, 0xa2, 0xe5,
+ 0x9a, 0xe8, 0xa5, 0x6f, 0x40, 0xad, 0x94, 0x30, 0xba, 0x49, 0x05, 0x3a,
+ 0x1e, 0x1b, 0xe1, 0x94, 0xa1, 0xba, 0x41, 0x00, 0xc0, 0x2f, 0x00, 0x00,
+ 0x0f, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0b,
+ 0x00, 0x02, 0x01, 0x00
+];
+
+ #[test]
+ fn test_tls_record_invalid_recordlength() {
+ let mut v = SERVER_HELLO1.to_vec();
+ let bytes = v.as_mut_slice();
+ bytes[4] = 0xff; // make record incomplete (longer than data)
+ let expected = Err(Err::Incomplete(Needed::new(196)));
+ let res = parse_tls_plaintext(bytes);
+ assert_eq!(res, expected);
+ }
+
+ #[test]
+ fn test_tls_record_invalid_recordlength2() {
+ let mut v = SERVER_HELLO1.to_vec();
+ let bytes = v.as_mut_slice();
+ bytes[4] = 0x00; // make record incomplete (shorter than data)
+ let res = parse_tls_plaintext(bytes);
+ assert!(res.is_err());
+ }
+
+ #[test]
+ fn test_tls_record_invalid_messagelength() {
+ let mut v = SERVER_HELLO1.to_vec();
+ let bytes = v.as_mut_slice();
+ bytes[8] = 0xff; // create message larger than record
+ let res = parse_tls_plaintext(bytes);
+ assert!(res.is_err());
+ }
+
+ #[test]
+ fn test_tls_record_invalid_messagelength2() {
+ let mut v = SERVER_HELLO1.to_vec();
+ let bytes = v.as_mut_slice();
+ bytes[8] = 0x01; // create message shorter than record
+ let res = parse_tls_plaintext(bytes);
+ assert!(res.is_err());
+ }
+
+ #[rustfmt::skip]
+static SERVER_CERTIFICATE_REQUEST_NOCA: &[u8] = &[
+ 0x16, 0x03, 0x03, 0x00, 0x2a, 0x0d, 0x00, 0x00, 0x26, 0x03, 0x01, 0x02,
+ 0x40, 0x00, 0x1e, 0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05, 0x01, 0x05,
+ 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x03, 0x01, 0x03,
+ 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, 0x00, 0x00
+];
+
+ #[test]
+ fn test_tls_record_cert_request_noca() {
+ let empty = &b""[..];
+ let bytes = SERVER_CERTIFICATE_REQUEST_NOCA;
+ let expected = TlsPlaintext {
+ hdr: TlsRecordHeader {
+ record_type: TlsRecordType::Handshake,
+ version: TlsVersion::Tls12,
+ len: bytes.len() as u16 - 5,
+ },
+ msg: vec![TlsMessage::Handshake(
+ TlsMessageHandshake::CertificateRequest(TlsCertificateRequestContents {
+ cert_types: vec![0x01, 0x02, 0x40],
+ sig_hash_algs: Some(vec![
+ 0x0601, 0x0602, 0x0603, 0x0501, 0x0502, 0x0503, 0x0401, 0x0402, 0x0403,
+ 0x0301, 0x0302, 0x0303, 0x0201, 0x0202, 0x0203,
+ ]),
+ unparsed_ca: vec![],
+ }),
+ )],
+ };
+ assert_eq!(parse_tls_plaintext(bytes), Ok((empty, expected)));
+ }
+
+ #[rustfmt::skip]
+static SERVER_CERTIFICATE_REQUEST_CA: &[u8] = &[
+ 0x16, 0x03, 0x03, 0x00, 0x73, 0x0d, 0x00, 0x00, 0x6f, 0x03, 0x01, 0x02,
+ 0x40, 0x00, 0x1e, 0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05, 0x01, 0x05,
+ 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x03, 0x01, 0x03,
+ 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, 0x00, 0x49, 0x00,
+ 0x47, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x46, 0x52, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18,
+ 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64
+];
+
+ #[test]
+ fn test_tls_record_cert_request_ca() {
+ let empty = &b""[..];
+ let bytes = SERVER_CERTIFICATE_REQUEST_CA;
+ let ca1 = &bytes[49..];
+ let expected = TlsPlaintext {
+ hdr: TlsRecordHeader {
+ record_type: TlsRecordType::Handshake,
+ version: TlsVersion::Tls12,
+ len: bytes.len() as u16 - 5,
+ },
+ msg: vec![TlsMessage::Handshake(
+ TlsMessageHandshake::CertificateRequest(TlsCertificateRequestContents {
+ cert_types: vec![0x01, 0x02, 0x40],
+ sig_hash_algs: Some(vec![
+ 0x0601, 0x0602, 0x0603, 0x0501, 0x0502, 0x0503, 0x0401, 0x0402, 0x0403,
+ 0x0301, 0x0302, 0x0303, 0x0201, 0x0202, 0x0203,
+ ]),
+ unparsed_ca: vec![ca1],
+ }),
+ )],
+ };
+ assert_eq!(parse_tls_plaintext(bytes), Ok((empty, expected)));
+ }
+
+ #[rustfmt::skip]
+static SERVER_STATUS_RESPONSE: &[u8] = &[
+ 0x16, 0x00, 0x06, 0x3f, 0x01, 0x00, 0x06, 0x3b, 0x30, 0x82, 0x06, 0x37,
+ 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x06, 0x30, 0x30, 0x82, 0x06, 0x2c, 0x06,
+ 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01, 0x04, 0x82,
+ 0x06, 0x1d, 0x30, 0x82, 0x06, 0x19, 0x30, 0x81, 0x9e, 0xa2, 0x16, 0x04,
+ 0x14, 0x9b, 0xe1, 0x51, 0x6a, 0xe3, 0xbe, 0x1a, 0x97, 0x21, 0x2b, 0x67,
+ 0xb1, 0x07, 0xd4, 0x54, 0x6c, 0x4f, 0xae, 0x53, 0x3c, 0x18, 0x0f, 0x32,
+ 0x30, 0x31, 0x36, 0x31, 0x30, 0x31, 0x32, 0x32, 0x33, 0x34, 0x32, 0x35,
+ 0x31, 0x5a, 0x30, 0x73, 0x30, 0x71, 0x30, 0x49, 0x30, 0x09, 0x06, 0x05,
+ 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x74, 0x24, 0x14,
+ 0x67, 0x06, 0x9f, 0xf5, 0xe0, 0x98, 0x3f, 0x5e, 0x3e, 0x1a, 0x6b, 0xa0,
+ 0x65, 0x2a, 0x54, 0x15, 0x75, 0x04, 0x14, 0x01, 0x59, 0xab, 0xe7, 0xdd,
+ 0x3a, 0x0b, 0x59, 0xa6, 0x64, 0x63, 0xd6, 0xcf, 0x20, 0x07, 0x57, 0xd5,
+ 0x91, 0xe7, 0x6a, 0x02, 0x10, 0x7e, 0x91, 0xc2, 0x1d, 0xe5, 0x0b, 0x21,
+ 0x74, 0x6d, 0x19, 0x78, 0xfa, 0x4b, 0xde, 0xbe, 0x48, 0x80, 0x00, 0x18,
+ 0x0f, 0x32, 0x30, 0x31, 0x36, 0x31, 0x30, 0x31, 0x32, 0x32, 0x33, 0x34,
+ 0x32, 0x35, 0x31, 0x5a, 0xa0, 0x11, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x36,
+ 0x31, 0x30, 0x31, 0x39, 0x32, 0x33, 0x34, 0x32, 0x35, 0x31, 0x5a, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+ 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xaa, 0x99, 0x41, 0xfe, 0x76,
+ 0x22, 0x24, 0x0c, 0x9e, 0xdb, 0x2a, 0xc7, 0xad, 0xe5, 0xf5, 0xf7, 0x0f,
+ 0x40, 0x2b, 0x04, 0x42, 0xb3, 0xe6, 0x0d, 0x4d, 0x52, 0xef, 0x0e, 0xd0,
+ 0xe7, 0x96, 0x99, 0x14, 0x95, 0xef, 0xda, 0x98, 0x25, 0x08, 0xda, 0x7f,
+ 0x8e, 0xbf, 0x0a, 0x63, 0x7c, 0xb0, 0x9f, 0x99, 0x41, 0x21, 0xd7, 0xf9,
+ 0x11, 0x0e, 0x60, 0x41, 0x24, 0x03, 0x87, 0x15, 0x08, 0xc7, 0x60, 0xe8,
+ 0x1c, 0xc6, 0x21, 0x7e, 0xc8, 0x08, 0x89, 0x7f, 0xbc, 0xa3, 0x75, 0x70,
+ 0x5c, 0xc6, 0x24, 0x24, 0x7a, 0x85, 0x49, 0x40, 0xdb, 0x20, 0x18, 0x75,
+ 0x0f, 0x94, 0x99, 0xb9, 0xcc, 0x4d, 0x8f, 0x06, 0xc8, 0xdf, 0x3a, 0xfc,
+ 0x33, 0x6d, 0x06, 0x9b, 0x00, 0xf3, 0x73, 0xfd, 0x04, 0x9a, 0xe0, 0x3c,
+ 0x2d, 0x14, 0xbd, 0x96, 0x8e, 0xf8, 0x01, 0xab, 0xb9, 0xc9, 0x0d, 0xb8,
+ 0xa6, 0x3f, 0x16, 0x07, 0x0e, 0x46, 0x7b, 0x76, 0xe5, 0x48, 0xfe, 0xc2,
+ 0xf6, 0xfa, 0x6c, 0xd9, 0x2e, 0xb4, 0x25, 0x20, 0x84, 0xd2, 0x6c, 0x8b,
+ 0xc6, 0x48, 0x14, 0x2d, 0x17, 0x06, 0x91, 0xd9, 0x66, 0x73, 0xf4, 0x47,
+ 0x2e, 0x81, 0x18, 0xa4, 0x72, 0xf1, 0x33, 0x12, 0x06, 0x3d, 0x12, 0xb6,
+ 0x59, 0x8f, 0xf8, 0xa2, 0x74, 0x74, 0x29, 0x69, 0xad, 0xc9, 0x1d, 0xc9,
+ 0x51, 0x08, 0x91, 0xf6, 0xda, 0xd6, 0xa6, 0x72, 0x46, 0xc4, 0x2a, 0x46,
+ 0x40, 0xf0, 0xa2, 0xb7, 0xd7, 0x3a, 0x8d, 0x47, 0x5b, 0xe0, 0xf3, 0x06,
+ 0x13, 0xf8, 0x40, 0xfa, 0xef, 0x70, 0x83, 0xfa, 0x9c, 0x5e, 0xfb, 0xe9,
+ 0x2d, 0xbd, 0x25, 0x37, 0x58, 0xff, 0xc1, 0xa1, 0x2a, 0x47, 0xbb, 0x81,
+ 0x31, 0x83, 0x74, 0xb1, 0x64, 0xd3, 0xf4, 0x1f, 0x88, 0x08, 0x9b, 0x4d,
+ 0x52, 0x5d, 0x7b, 0xcf, 0x82, 0x1f, 0xd7, 0x05, 0x79, 0x1d, 0x95, 0xa0,
+ 0x82, 0x04, 0x60, 0x30, 0x82, 0x04, 0x5c, 0x30, 0x82, 0x04, 0x58, 0x30,
+ 0x82, 0x03, 0x40, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x30, 0x69,
+ 0x79, 0x69, 0x01, 0x5d, 0xf2, 0x7c, 0x9f, 0x97, 0x0c, 0xd1, 0x93, 0xb4,
+ 0x56, 0x38, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x77, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1d, 0x30, 0x1b,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x14, 0x53, 0x79, 0x6d, 0x61, 0x6e,
+ 0x74, 0x65, 0x63, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b,
+ 0x13, 0x16, 0x53, 0x79, 0x6d, 0x61, 0x6e, 0x74, 0x65, 0x63, 0x20, 0x54,
+ 0x72, 0x75, 0x73, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
+ 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1f, 0x53,
+ 0x79, 0x6d, 0x61, 0x6e, 0x74, 0x65, 0x63, 0x20, 0x43, 0x6c, 0x61, 0x73,
+ 0x73, 0x20, 0x33, 0x20, 0x45, 0x56, 0x20, 0x53, 0x53, 0x4c, 0x20, 0x43,
+ 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36,
+ 0x30, 0x38, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17,
+ 0x0d, 0x31, 0x36, 0x31, 0x31, 0x32, 0x32, 0x32, 0x33, 0x35, 0x39, 0x35,
+ 0x39, 0x5a, 0x30, 0x39, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x2e, 0x53, 0x79, 0x6d, 0x61, 0x6e, 0x74, 0x65, 0x63, 0x20,
+ 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x45, 0x56, 0x20, 0x53,
+ 0x53, 0x4c, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x20, 0x4f,
+ 0x43, 0x53, 0x50, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65,
+ 0x72, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f,
+ 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xbe, 0x8e,
+ 0xc9, 0x7c, 0x69, 0xd3, 0x09, 0x45, 0xd4, 0x5f, 0xa1, 0xc7, 0xe7, 0x8d,
+ 0xdd, 0xbe, 0x9e, 0x17, 0x01, 0x8a, 0x6c, 0xb0, 0x57, 0xb9, 0x98, 0xfb,
+ 0x2f, 0x07, 0xa4, 0xde, 0xc9, 0x0f, 0x4b, 0x9f, 0x26, 0xc9, 0x77, 0x90,
+ 0xe6, 0xc0, 0xd0, 0xc2, 0xef, 0xc2, 0xc9, 0x3b, 0x4b, 0x86, 0xe0, 0xaf,
+ 0xc7, 0x87, 0xef, 0x9a, 0xbf, 0x26, 0x33, 0x95, 0x55, 0xf2, 0x7b, 0xa6,
+ 0x95, 0x86, 0x7d, 0x0d, 0x91, 0x82, 0xa8, 0x2c, 0x8a, 0xe5, 0x5c, 0x60,
+ 0xb7, 0x98, 0x01, 0xec, 0xd0, 0x76, 0x2d, 0xd7, 0x3e, 0xaf, 0x6b, 0xc0,
+ 0x35, 0xd0, 0x3a, 0xc1, 0xdf, 0x46, 0x84, 0xdf, 0x98, 0xdf, 0x09, 0xec,
+ 0xdf, 0x82, 0xc4, 0x0f, 0x05, 0xc9, 0xdb, 0x66, 0x87, 0xb6, 0x4d, 0x25,
+ 0x7d, 0x23, 0x43, 0x48, 0x71, 0x1c, 0x86, 0x21, 0xb2, 0x4f, 0xec, 0xf7,
+ 0x03, 0xd1, 0xf4, 0x4b, 0x74, 0x13, 0x03, 0xd7, 0x85, 0xfe, 0xcd, 0xf5,
+ 0xed, 0xf4, 0x89, 0xb1, 0x64, 0x1a, 0x2c, 0x4f, 0x2f, 0xee, 0xc5, 0x98,
+ 0xec, 0xb7, 0xee, 0xab, 0x10, 0x2e, 0x8b, 0x5b, 0x59, 0x7e, 0x97, 0xcc,
+ 0xc9, 0xd6, 0xa7, 0xa5, 0x3a, 0xde, 0x5a, 0x1a, 0xe6, 0x17, 0x17, 0xba,
+ 0xc8, 0x94, 0x1b, 0x2e, 0xbc, 0x28, 0xb2, 0x5a, 0x6b, 0x0a, 0x81, 0x72,
+ 0x51, 0xdd, 0x07, 0xed, 0x43, 0xcb, 0xde, 0xf4, 0xee, 0x41, 0x48, 0x56,
+ 0x03, 0x8b, 0x9b, 0x1d, 0xc4, 0xe2, 0x3b, 0xae, 0x9f, 0xe2, 0xc5, 0x63,
+ 0xca, 0xd9, 0x69, 0x30, 0x38, 0x87, 0x7e, 0x57, 0xaa, 0xa3, 0x4d, 0x30,
+ 0x5f, 0xe7, 0x4d, 0xe9, 0x5c, 0xc1, 0x32, 0xec, 0x58, 0xc7, 0x88, 0xea,
+ 0xa5, 0xd2, 0x92, 0xe2, 0x17, 0x8f, 0x9b, 0x25, 0xbf, 0xc5, 0xac, 0x16,
+ 0xdb, 0xde, 0xf2, 0x38, 0xf8, 0xf7, 0xe7, 0xe2, 0xe6, 0xcf, 0xdf, 0x9b,
+ 0x91, 0x7f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x1c, 0x30,
+ 0x82, 0x01, 0x18, 0x30, 0x0f, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x30, 0x01, 0x05, 0x04, 0x02, 0x05, 0x00, 0x30, 0x22, 0x06, 0x03,
+ 0x55, 0x1d, 0x11, 0x04, 0x1b, 0x30, 0x19, 0xa4, 0x17, 0x30, 0x15, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x54, 0x47,
+ 0x56, 0x2d, 0x44, 0x2d, 0x31, 0x37, 0x31, 0x39, 0x30, 0x1f, 0x06, 0x03,
+ 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x01, 0x59, 0xab,
+ 0xe7, 0xdd, 0x3a, 0x0b, 0x59, 0xa6, 0x64, 0x63, 0xd6, 0xcf, 0x20, 0x07,
+ 0x57, 0xd5, 0x91, 0xe7, 0x6a, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0x9b, 0xe1, 0x51, 0x6a, 0xe3, 0xbe, 0x1a, 0x97,
+ 0x21, 0x2b, 0x67, 0xb1, 0x07, 0xd4, 0x54, 0x6c, 0x4f, 0xae, 0x53, 0x3c,
+ 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02,
+ 0x30, 0x00, 0x30, 0x6e, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x67, 0x30,
+ 0x65, 0x30, 0x63, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x45,
+ 0x01, 0x07, 0x17, 0x03, 0x30, 0x54, 0x30, 0x26, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1a, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x79, 0x6d, 0x61, 0x75,
+ 0x74, 0x68, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x70, 0x73, 0x30, 0x2a,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x1e,
+ 0x1a, 0x1c, 0x20, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
+ 0x77, 0x77, 0x2e, 0x73, 0x79, 0x6d, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x2f, 0x72, 0x70, 0x61, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d,
+ 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x03, 0x09, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
+ 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x01, 0x00, 0x55, 0x8a, 0xbf, 0xb5, 0x01, 0xee, 0xc2, 0x12, 0x7f,
+ 0xa4, 0xf9, 0x8e, 0xec, 0xb6, 0x8c, 0x40, 0x10, 0x91, 0x7b, 0x84, 0xa3,
+ 0xc5, 0x3c, 0x12, 0x5d, 0xc4, 0x79, 0x55, 0xbf, 0xf9, 0xf0, 0x74, 0xfd,
+ 0x9c, 0xd6, 0xae, 0x9e, 0x4b, 0x90, 0x04, 0x2e, 0xfd, 0x8f, 0xf8, 0x6b,
+ 0x6c, 0x0b, 0x3f, 0x2b, 0x94, 0xaa, 0xc2, 0xe3, 0x07, 0xc6, 0xbe, 0xcc,
+ 0x33, 0xe1, 0x68, 0x7e, 0x43, 0x8b, 0xd9, 0x36, 0x17, 0xb0, 0x32, 0x87,
+ 0xec, 0xe1, 0x10, 0x4d, 0x72, 0x26, 0xad, 0xd5, 0xa5, 0xa2, 0x9a, 0xf3,
+ 0x54, 0x21, 0x78, 0x0e, 0xdb, 0xa6, 0xba, 0xa5, 0x2e, 0x7f, 0x4d, 0xc6,
+ 0x5a, 0xcd, 0xa5, 0xfd, 0x38, 0x0d, 0x34, 0x9d, 0xe0, 0x88, 0xd7, 0x51,
+ 0x40, 0xd8, 0x73, 0xf3, 0x0c, 0xec, 0x53, 0x8f, 0x4e, 0x74, 0xda, 0xd3,
+ 0x3c, 0x67, 0x23, 0xba, 0x0f, 0x1c, 0xa8, 0x46, 0x32, 0x19, 0x3a, 0xbc,
+ 0xad, 0x4d, 0x3e, 0xd3, 0x4f, 0x89, 0xa9, 0xe9, 0xb8, 0x00, 0x1e, 0x1d,
+ 0x04, 0xb5, 0x7f, 0x31, 0xfd, 0xc0, 0x9e, 0xd0, 0xa8, 0xad, 0x46, 0xab,
+ 0x06, 0x91, 0x3f, 0xf4, 0xae, 0xce, 0xb7, 0x47, 0xb2, 0x4d, 0xcf, 0x93,
+ 0x5b, 0x4c, 0x62, 0xf2, 0x43, 0xd6, 0xd1, 0xde, 0x27, 0x33, 0xe0, 0x64,
+ 0xa9, 0x0e, 0x83, 0xa0, 0x93, 0x3c, 0xe8, 0xb2, 0xa0, 0x60, 0xb5, 0xcd,
+ 0x48, 0x51, 0x1e, 0x66, 0x00, 0x46, 0xcd, 0xe5, 0x22, 0x9f, 0x55, 0x2a,
+ 0xdc, 0xea, 0x61, 0xb3, 0xe5, 0x84, 0x81, 0x36, 0x29, 0x06, 0x6a, 0x1f,
+ 0xe0, 0x48, 0x11, 0x53, 0xb0, 0x60, 0xcf, 0x88, 0x06, 0xc7, 0xbc, 0xb9,
+ 0x57, 0xbe, 0x06, 0x12, 0xbf, 0x33, 0x8d, 0xc9, 0xe6, 0xa7, 0x36, 0x44,
+ 0xb8, 0x67, 0x0b, 0xa7, 0xe3, 0x0e, 0xbb, 0xdf, 0x5c, 0xd8, 0x56, 0xcd,
+ 0x25, 0x44, 0x93, 0xc9, 0x56, 0x22, 0xea
+];
+
+ #[test]
+ fn test_tls_message_status_response() {
+ let empty = &b""[..];
+ let bytes = SERVER_STATUS_RESPONSE;
+ let blob = &bytes[8..];
+ let expected = vec![TlsMessage::Handshake(
+ TlsMessageHandshake::CertificateStatus(TlsCertificateStatusContents {
+ status_type: 1,
+ blob,
+ }),
+ )];
+ let hdr = TlsRecordHeader {
+ record_type: TlsRecordType::Handshake,
+ version: TlsVersion(0),
+ len: 0x0,
+ };
+ let res = parse_tls_record_with_header(bytes, &hdr);
+ assert_eq!(res, Ok((empty, expected)));
+ }
+} // mod tls_handshake
diff --git a/rust/vendor/tls-parser/tests/tls_tls13.rs b/rust/vendor/tls-parser/tests/tls_tls13.rs
new file mode 100644
index 0000000..dfdc874
--- /dev/null
+++ b/rust/vendor/tls-parser/tests/tls_tls13.rs
@@ -0,0 +1,122 @@
+extern crate nom;
+extern crate tls_parser;
+
+mod tls_13 {
+ use tls_parser::*;
+
+ // Test vectors from https://tools.ietf.org/html/draft-thomson-tls-tls13-vectors-01
+ #[rustfmt::skip]
+static TV_CLIENT_HELLO_1: &[u8] = &[
+ 0x16, 0x03, 0x01, 0x02, 0x00, 0x01, 0x00, 0x01, 0xfc, 0x03, 0x03, 0xce, 0x05, 0xcf, 0xa3, 0xd9,
+ 0x21, 0x70, 0xcb, 0xc2, 0x46, 0x5c, 0xdc, 0x3e, 0x3a, 0x2f, 0x57, 0x7f, 0x6e, 0xac, 0x80, 0x93,
+ 0x61, 0x70, 0x8a, 0xb2, 0x44, 0xb0, 0x7d, 0x8f, 0xad, 0x86, 0x16, 0x00, 0x00, 0x3e, 0x13, 0x01,
+ 0x13, 0x03, 0x13, 0x02, 0xc0, 0x2b, 0xc0, 0x2f, 0xcc, 0xa9, 0xcc, 0xa8, 0xc0, 0x0a, 0xc0, 0x09,
+ 0xc0, 0x13, 0xc0, 0x23, 0xc0, 0x27, 0xc0, 0x14, 0x00, 0x9e, 0xcc, 0xaa, 0x00, 0x33, 0x00, 0x32,
+ 0x00, 0x67, 0x00, 0x39, 0x00, 0x38, 0x00, 0x6b, 0x00, 0x16, 0x00, 0x13, 0x00, 0x9c, 0x00, 0x2f,
+ 0x00, 0x3c, 0x00, 0x35, 0x00, 0x3d, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x04, 0x01, 0x00, 0x01, 0x95,
+ 0x00, 0x15, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0xff,
+ 0x01, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x12, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
+ 0x00, 0x19, 0x01, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03, 0x01, 0x04, 0x00, 0x0b, 0x00, 0x02,
+ 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x28, 0x00, 0x26, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20,
+ 0x2a, 0x98, 0x1d, 0xb6, 0xcd, 0xd0, 0x2a, 0x06, 0xc1, 0x76, 0x31, 0x02, 0xc9, 0xe7, 0x41, 0x36,
+ 0x5a, 0xc4, 0xe6, 0xf7, 0x2b, 0x31, 0x76, 0xa6, 0xbd, 0x6a, 0x35, 0x23, 0xd3, 0xec, 0x0f, 0x4c,
+ 0x00, 0x2b, 0x00, 0x07, 0x06, 0x7f, 0x12, 0x03, 0x03, 0x03, 0x02, 0x00, 0x0d, 0x00, 0x20, 0x00,
+ 0x1e, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02, 0x03, 0x08, 0x04, 0x08, 0x05, 0x08, 0x06, 0x04,
+ 0x01, 0x05, 0x01, 0x06, 0x01, 0x02, 0x01, 0x04, 0x02, 0x05, 0x02, 0x06, 0x02, 0x02, 0x02, 0x00,
+ 0x2d, 0x00, 0x02, 0x01, 0x01,
+];
+
+ #[rustfmt::skip]
+static TV_SERVER_HELLO_1: &[u8] = &[
+ 0x16, 0x03, 0x01, 0x00, 0x52, 0x02, 0x00, 0x00, 0x4e, 0x7f, 0x12, 0x20, 0xb9, 0xc9, 0x20, 0x1c,
+ 0xd1, 0x71, 0xa1, 0x5a, 0xbb, 0xa4, 0xe7, 0xed, 0xdc, 0xf3, 0xe8, 0x48, 0x8e, 0x71, 0x92, 0xff,
+ 0xe0, 0x1e, 0xa5, 0xc1, 0x9f, 0x3d, 0x4b, 0x52, 0xff, 0xee, 0xbe, 0x13, 0x01, 0x00, 0x28, 0x00,
+ 0x28, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0x9c, 0x1b, 0x0a, 0x74, 0x21, 0x91, 0x9a, 0x73, 0xcb,
+ 0x57, 0xb3, 0xa0, 0xad, 0x9d, 0x68, 0x05, 0x86, 0x1a, 0x9c, 0x47, 0xe1, 0x1d, 0xf8, 0x63, 0x9d,
+ 0x25, 0x32, 0x3b, 0x79, 0xce, 0x20, 0x1c,
+];
+
+ #[test]
+ fn test_tls13_ch() {
+ let empty = &b""[..];
+ let bytes = TV_CLIENT_HELLO_1;
+ let ciphers = vec![
+ 0x1301, 0x1303, 0x1302, 0xc02b, 0xc02f, 0xcca9, 0xcca8, 0xc00a, 0xc009, 0xc013, 0xc023,
+ 0xc027, 0xc014, 0x009e, 0xccaa, 0x0033, 0x0032, 0x0067, 0x0039, 0x0038, 0x006b, 0x0016,
+ 0x0013, 0x009c, 0x002f, 0x003c, 0x0035, 0x003d, 0x000a, 0x0005, 0x0004,
+ ];
+ let expected_ch = TlsPlaintext {
+ hdr: TlsRecordHeader {
+ record_type: TlsRecordType::Handshake,
+ version: TlsVersion::Tls10,
+ len: 512,
+ },
+ msg: vec![TlsMessage::Handshake(TlsMessageHandshake::ClientHello(
+ TlsClientHelloContents {
+ version: TlsVersion::Tls12,
+ rand_time: 0xce05_cfa3,
+ rand_data: &bytes[15..15 + 28],
+ session_id: None,
+ ciphers: ciphers.iter().map(|&x| TlsCipherSuiteID(x)).collect(),
+ comp: vec![TlsCompressionID(0)],
+ ext: Some(&bytes[112..]),
+ },
+ ))],
+ };
+ let ires = parse_tls_plaintext(bytes);
+ assert_eq!(ires, Ok((empty, expected_ch)));
+ }
+
+ #[test]
+ fn test_tls13_sh() {
+ let empty = &b""[..];
+ let bytes = TV_SERVER_HELLO_1;
+ let expected_sh = TlsPlaintext {
+ hdr: TlsRecordHeader {
+ record_type: TlsRecordType::Handshake,
+ version: TlsVersion::Tls10,
+ len: 82,
+ },
+ msg: vec![TlsMessage::Handshake(
+ TlsMessageHandshake::ServerHelloV13Draft18(TlsServerHelloV13Draft18Contents {
+ version: TlsVersion::Tls13Draft18,
+ random: &bytes[11..11 + 32],
+ cipher: TlsCipherSuiteID(0x1301),
+ ext: Some(&bytes[47..]),
+ }),
+ )],
+ };
+ let expected_ext = vec![TlsExtension::KeyShareOld(&bytes[51..])];
+ let ires = parse_tls_plaintext(bytes);
+ assert_eq!(ires, Ok((empty, expected_sh)));
+ let res = ires.unwrap();
+
+ let msg = &res.1.msg[0];
+ let ext_raw = match *msg {
+ TlsMessage::Handshake(TlsMessageHandshake::ServerHelloV13Draft18(ref sh)) => {
+ sh.ext.unwrap()
+ }
+ _ => {
+ panic!("Extensions parsing failed");
+ }
+ };
+ let res_ext = parse_tls_extensions(ext_raw);
+ assert_eq!(res_ext, Ok((empty, expected_ext)));
+ }
+} // mod tls_13