diff options
Diffstat (limited to 'rust/vendor/tls-parser')
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 |