tls-parser-0.9.2/Cargo.toml.orig010064400017500001750000000020761356670754700147570ustar0000000000000000[package] description = "Parser for the TLS protocol" license = "MIT/Apache-2.0" keywords = ["TLS","SSL","protocol","parser","nom"] homepage = "https://github.com/rusticata/tls-parser" repository = "https://github.com/rusticata/tls-parser.git" documentation = "https://docs.rs/tls-parser" name = "tls-parser" version = "0.9.2" authors = ["Pierre Chifflier "] categories = ["network-programming", "parser-implementations"] edition = "2018" readme = "README.md" 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" ] [lib] name = "tls_parser" [features] default = [] serialize = ["cookie-factory"] [dependencies] nom = "5.0" phf = "0.8" enum_primitive = "^0.1" rusticata-macros = "2.0" cookie-factory = { version="0.3", optional=true } [dev-dependencies] pretty_assertions = "0.6" [build-dependencies] phf_codegen = "0.8" [badges] travis-ci = { repository = "rusticata/tls-parser" } tls-parser-0.9.2/Cargo.toml0000644000000032320000000000000111750ustar00# 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 believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "tls-parser" version = "0.9.2" authors = ["Pierre Chifflier "] 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 = "5.0" [dependencies.phf] version = "0.8" [dependencies.rusticata-macros] version = "2.0" [dev-dependencies.pretty_assertions] version = "0.6" [build-dependencies.phf_codegen] version = "0.8" [features] default = [] serialize = ["cookie-factory"] [badges.travis-ci] repository = "rusticata/tls-parser" tls-parser-0.9.2/LICENSE-APACHE010064400017500001750000000251371322757470500140070ustar0000000000000000 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. tls-parser-0.9.2/LICENSE-MIT010064400017500001750000000020441322757470500135070ustar0000000000000000Copyright (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. tls-parser-0.9.2/benches/bench_dh.rs010064400017500001750000000057441355234366100155700ustar0000000000000000#![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: &'static [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 tls-parser-0.9.2/benches/bench_handshake.rs010064400017500001750000000642431355234366100171220ustar0000000000000000#![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: &'static [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: &'static [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 tls-parser-0.9.2/build.rs010064400017500001750000000053311355234366100135160ustar0000000000000000extern crate phf_codegen; use std::env; use std::error::Error; 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::() } else { c.to_lowercase().collect::() } }) .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.description()), 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 = {};", map.build() ) .unwrap(); } tls-parser-0.9.2/scripts/extract-iana-ciphers.py010075500017500001750000000102731356670714600201400ustar0000000000000000#!/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) tls-parser-0.9.2/scripts/tls-ciphersuites.txt010064400017500001750000001055731356670714600176300ustar00000000000000000000: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:1:0300:0302 0004:TLS_RSA_WITH_RC4_128_MD5:RSA:RSA:RC4::128:HMAC-MD5:128:DEFAULT:0:rfc5246:0:0300:ffff 0005:TLS_RSA_WITH_RC4_128_SHA:RSA:RSA:RC4::128:HMAC-SHA1:160:DEFAULT:0:rfc5246: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:0302 0007:TLS_RSA_WITH_IDEA_CBC_SHA:RSA:RSA:IDEA:CBC:128:HMAC-SHA1:160:DEFAULT:0:rfc5469:0:0300:ffff 0008:TLS_RSA_EXPORT_WITH_DES40_CBC_SHA:RSA:RSA:DES:CBC:40:HMAC-SHA1:160:DEFAULT:0:rfc4346:1:0300:0302 0009:TLS_RSA_WITH_DES_CBC_SHA:RSA:RSA:DES:CBC:56:HMAC-SHA1:160:DEFAULT:0:rfc5469: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:0302 000c:TLS_DH_DSS_WITH_DES_CBC_SHA:DH:DSS:DES:CBC:56:HMAC-SHA1:160:DEFAULT:0:rfc5469: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:0302 000f:TLS_DH_RSA_WITH_DES_CBC_SHA:DH:RSA:DES:CBC:56:HMAC-SHA1:160:DEFAULT:0:rfc5469: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:0302 0012:TLS_DHE_DSS_WITH_DES_CBC_SHA:DHE:DSS:DES:CBC:56:HMAC-SHA1:160:DEFAULT:0:rfc5469: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:0302 0015:TLS_DHE_RSA_WITH_DES_CBC_SHA:DHE:RSA:DES:CBC:56:HMAC-SHA1:160:DEFAULT:0:rfc5469: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:1:0300:0302 0018:TLS_DH_anon_WITH_RC4_128_MD5:DH:NULL:RC4::128:HMAC-MD5:128:DEFAULT:0:rfc5246: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:0302 001a:TLS_DH_anon_WITH_DES_CBC_SHA:DH:NULL:DES:CBC:56:HMAC-SHA1:160:DEFAULT:0:rfc5469: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: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: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:0302 0027:TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA:KRB5:KRB5:RC2:CBC:40:HMAC-SHA1:160:DEFAULT:0:rfc2712:1:0300:0302 0028:TLS_KRB5_EXPORT_WITH_RC4_40_SHA:KRB5:KRB5:RC4::40:HMAC-SHA1:160:DEFAULT:0:rfc2712:1:0300:0302 0029:TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5:KRB5:KRB5:DES:CBC:40:HMAC-MD5:128:DEFAULT:0:rfc2712:1:0300:0302 002a:TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5:KRB5:KRB5:RC2:CBC:40:HMAC-MD5:128:DEFAULT:0:rfc2712:1:0300:0302 002b:TLS_KRB5_EXPORT_WITH_RC4_40_MD5:KRB5:KRB5:RC4::40:HMAC-MD5:128:DEFAULT:0:rfc2712:1:0300:0302 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:0303:ffff 003c:TLS_RSA_WITH_AES_128_CBC_SHA256:RSA:RSA:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5246:0:0303:ffff 003d:TLS_RSA_WITH_AES_256_CBC_SHA256:RSA:RSA:AES:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5246:0:0303:ffff 003e:TLS_DH_DSS_WITH_AES_128_CBC_SHA256:DH:DSS:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5246:0:0303:ffff 003f:TLS_DH_RSA_WITH_AES_128_CBC_SHA256:DH:RSA:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5246:0:0303:ffff 0040:TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:DHE:DSS:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5246:0:0303: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:0303:ffff 0068:TLS_DH_DSS_WITH_AES_256_CBC_SHA256:DH:DSS:AES:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5246:0:0303:ffff 0069:TLS_DH_RSA_WITH_AES_256_CBC_SHA256:DH:RSA:AES:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5246:0:0303:ffff 006a:TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:DHE:DSS:AES:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5246:0:0303:ffff 006b:TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:DHE:RSA:AES:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5246:0:0303:ffff 006c:TLS_DH_anon_WITH_AES_128_CBC_SHA256:DH:NULL:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5246:0:0303:ffff 006d:TLS_DH_anon_WITH_AES_256_CBC_SHA256:DH:NULL:AES:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5246:0:0303: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: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: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: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:0303:ffff 009d:TLS_RSA_WITH_AES_256_GCM_SHA384:RSA:RSA:AES:GCM:256:AEAD:256:SHA384:384:rfc5288:0:0303:ffff 009e:TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:DHE:RSA:AES:GCM:128:AEAD:128:SHA256:256:rfc5288:0:0303:ffff 009f:TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:DHE:RSA:AES:GCM:256:AEAD:256:SHA384:384:rfc5288:0:0303:ffff 00a0:TLS_DH_RSA_WITH_AES_128_GCM_SHA256:DH:RSA:AES:GCM:128:AEAD:128:SHA256:256:rfc5288:0:0303:ffff 00a1:TLS_DH_RSA_WITH_AES_256_GCM_SHA384:DH:RSA:AES:GCM:256:AEAD:256:SHA384:384:rfc5288:0:0303:ffff 00a2:TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:DHE:DSS:AES:GCM:128:AEAD:128:SHA256:256:rfc5288:0:0303:ffff 00a3:TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:DHE:DSS:AES:GCM:256:AEAD:256:SHA384:384:rfc5288:0:0303:ffff 00a4:TLS_DH_DSS_WITH_AES_128_GCM_SHA256:DH:DSS:AES:GCM:128:AEAD:128:SHA256:256:rfc5288:0:0303:ffff 00a5:TLS_DH_DSS_WITH_AES_256_GCM_SHA384:DH:DSS:AES:GCM:256:AEAD:256:SHA384:384:rfc5288:0:0303:ffff 00a6:TLS_DH_anon_WITH_AES_128_GCM_SHA256:DH:NULL:AES:GCM:128:AEAD:128:SHA256:256:rfc5288:0:0303:ffff 00a7:TLS_DH_anon_WITH_AES_256_GCM_SHA384:DH:NULL:AES:GCM:256:AEAD:256:SHA384:384:rfc5288:0:0303:ffff 00a8:TLS_PSK_WITH_AES_128_GCM_SHA256:PSK:PSK:AES:GCM:128:AEAD:128:SHA256:256:rfc5487:0:0303:ffff 00a9:TLS_PSK_WITH_AES_256_GCM_SHA384:PSK:PSK:AES:GCM:256:AEAD:256:SHA384:384:rfc5487:0:0303:ffff 00aa:TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:DHE:PSK:AES:GCM:128:AEAD:128:SHA256:256:rfc5487:0:0303:ffff 00ab:TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:DHE:PSK:AES:GCM:256:AEAD:256:SHA384:384:rfc5487:0:0303:ffff 00ac:TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:RSA:PSK:AES:GCM:128:AEAD:128:SHA256:256:rfc5487:0:0303:ffff 00ad:TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:RSA:PSK:AES:GCM:256:AEAD:256:SHA384:384:rfc5487:0:0303:ffff 00ae:TLS_PSK_WITH_AES_128_CBC_SHA256:PSK:PSK:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5487:0:0303:ffff 00af:TLS_PSK_WITH_AES_256_CBC_SHA384:PSK:PSK:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5487:0:0303:ffff 00b0:TLS_PSK_WITH_NULL_SHA256:PSK:PSK:NULL::0:HMAC-SHA256:256:SHA256:256:rfc5487:0:0303:ffff 00b1:TLS_PSK_WITH_NULL_SHA384:PSK:PSK:NULL::0:HMAC-SHA384:384:SHA384:384:rfc5487:0:0303:ffff 00b2:TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:DHE:PSK:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5487:0:0303:ffff 00b3:TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:DHE:PSK:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5487:0:0303:ffff 00b4:TLS_DHE_PSK_WITH_NULL_SHA256:DHE:PSK:NULL::0:HMAC-SHA256:256:SHA256:256:rfc5487:0:0303:ffff 00b5:TLS_DHE_PSK_WITH_NULL_SHA384:DHE:PSK:NULL::0:HMAC-SHA384:384:SHA384:384:rfc5487:0:0303:ffff 00b6:TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:RSA:PSK:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5487:0:0303:ffff 00b7:TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:RSA:PSK:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5487:0:0303:ffff 00b8:TLS_RSA_PSK_WITH_NULL_SHA256:RSA:PSK:NULL::0:HMAC-SHA256:256:SHA256:256:rfc5487:0:0303:ffff 00b9:TLS_RSA_PSK_WITH_NULL_SHA384:RSA:PSK:NULL::0:HMAC-SHA384:384:SHA384:384:rfc5487:0:0303:ffff 00ba:TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:RSA:RSA:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5932:0:0303:ffff 00bb:TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:DH:DSS:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5932:0:0303:ffff 00bc:TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:DH:RSA:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5932:0:0303:ffff 00bd:TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:DHE:DSS:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5932:0:0303:ffff 00be:TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:DHE:RSA:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5932:0:0303:ffff 00bf:TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256:DH:NULL:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5932:0:0303:ffff 00c0:TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:RSA:RSA:CAMELLIA:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5932:0:0303:ffff 00c1:TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:DH:DSS:CAMELLIA:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5932:0:0303:ffff 00c2:TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:DH:RSA:CAMELLIA:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5932:0:0303:ffff 00c3:TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:DHE:DSS:CAMELLIA:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5932:0:0303:ffff 00c4:TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:DHE:RSA:CAMELLIA:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5932:0:0303:ffff 00c5:TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256:DH:NULL:CAMELLIA:CBC:256:HMAC-SHA256:256:SHA256:256:rfc5932:0:0303:ffff 1301:TLS_AES_128_GCM_SHA256:TLS13:TLS13:AES:GCM:128:AEAD:128:SHA256:256:rfc8446:0:0303:ffff 1302:TLS_AES_256_GCM_SHA384:TLS13:TLS13:AES:GCM:256:AEAD:256:SHA384:384:rfc8446:0:0303:ffff 1303:TLS_CHACHA20_POLY1305_SHA256:TLS13:TLS13:CHACHA20_POLY1305:CBC:256:AEAD:256:SHA256:256:rfc8446:0:0303:ffff 1304:TLS_AES_128_CCM_SHA256:TLS13:TLS13:AES:CCM:128:AEAD:128:SHA256:256:rfc8446:0:0303:ffff 1305:TLS_AES_128_CCM_8_SHA256:TLS13:TLS13:AES:CCM:128:AEAD:128:SHA256:256:rfc8446:0:0303:ffff 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: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: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: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: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: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:0303:ffff c024:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:ECDHE:ECDSA:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5289:0:0303:ffff c025:TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:ECDH:ECDSA:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5289:0:0303:ffff c026:TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:ECDH:ECDSA:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5289:0:0303:ffff c027:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:ECDHE:RSA:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5289:0:0303:ffff c028:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:ECDHE:RSA:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5289:0:0303:ffff c029:TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:ECDH:RSA:AES:CBC:128:HMAC-SHA256:256:SHA256:256:rfc5289:0:0303:ffff c02a:TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:ECDH:RSA:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5289:0:0303:ffff c02b:TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:ECDHE:ECDSA:AES:GCM:128:AEAD:128:SHA256:256:rfc5289:0:0303:ffff c02c:TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:ECDHE:ECDSA:AES:GCM:256:AEAD:256:SHA384:384:rfc5289:0:0303:ffff c02d:TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:ECDH:ECDSA:AES:GCM:128:AEAD:128:SHA256:256:rfc5289:0:0303:ffff c02e:TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:ECDH:ECDSA:AES:GCM:256:AEAD:256:SHA384:384:rfc5289:0:0303:ffff c02f:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:ECDHE:RSA:AES:GCM:128:AEAD:128:SHA256:256:rfc5289:0:0303:ffff c030:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:ECDHE:RSA:AES:GCM:256:AEAD:256:SHA384:384:rfc5289:0:0303:ffff c031:TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:ECDH:RSA:AES:GCM:128:AEAD:128:SHA256:256:rfc5289:0:0303:ffff c032:TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:ECDH:RSA:AES:GCM:256:AEAD:256:SHA384:384:rfc5289:0:0303:ffff c033:TLS_ECDHE_PSK_WITH_RC4_128_SHA:ECDHE:PSK:RC4::128:HMAC-SHA1:160:DEFAULT:0:rfc5489: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:0303:ffff c038:TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:ECDHE:PSK:AES:CBC:256:HMAC-SHA384:384:SHA384:384:rfc5489:0:0303: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:0303:ffff c03b:TLS_ECDHE_PSK_WITH_NULL_SHA384:ECDHE:PSK:NULL::0:HMAC-SHA384:384:SHA384:384:rfc5489:0:0303:ffff c03c:TLS_RSA_WITH_ARIA_128_CBC_SHA256:RSA:RSA:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0303:ffff c03d:TLS_RSA_WITH_ARIA_256_CBC_SHA384:RSA:RSA:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0303:ffff c03e:TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256:DH:DSS:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0303:ffff c03f:TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384:DH:DSS:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0303:ffff c040:TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256:DH:RSA:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0303:ffff c041:TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384:DH:RSA:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0303:ffff c042:TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256:DHE:DSS:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0303:ffff c043:TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384:DHE:DSS:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0303:ffff c044:TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256:DHE:RSA:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0303:ffff c045:TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384:DHE:RSA:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0303:ffff c046:TLS_DH_anon_WITH_ARIA_128_CBC_SHA256:DH:NULL:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0303:ffff c047:TLS_DH_anon_WITH_ARIA_256_CBC_SHA384:DH:NULL:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0303:ffff c048:TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256:ECDHE:ECDSA:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0303:ffff c049:TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384:ECDHE:ECDSA:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0303:ffff c04a:TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256:ECDH:ECDSA:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0303:ffff c04b:TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384:ECDH:ECDSA:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0303:ffff c04c:TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256:ECDHE:RSA:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0303:ffff c04d:TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384:ECDHE:RSA:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0303:ffff c04e:TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256:ECDH:RSA:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0303:ffff c04f:TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384:ECDH:RSA:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0303:ffff c050:TLS_RSA_WITH_ARIA_128_GCM_SHA256:RSA:RSA:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0303:ffff c051:TLS_RSA_WITH_ARIA_256_GCM_SHA384:RSA:RSA:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0303:ffff c052:TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256:DHE:RSA:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0303:ffff c053:TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384:DHE:RSA:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0303:ffff c054:TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256:DH:RSA:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0303:ffff c055:TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384:DH:RSA:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0303:ffff c056:TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256:DHE:DSS:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0303:ffff c057:TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384:DHE:DSS:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0303:ffff c058:TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256:DH:DSS:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0303:ffff c059:TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384:DH:DSS:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0303:ffff c05a:TLS_DH_anon_WITH_ARIA_128_GCM_SHA256:DH:NULL:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0303:ffff c05b:TLS_DH_anon_WITH_ARIA_256_GCM_SHA384:DH:NULL:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0303:ffff c05c:TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256:ECDHE:ECDSA:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0303:ffff c05d:TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384:ECDHE:ECDSA:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0303:ffff c05e:TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256:ECDH:ECDSA:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0303:ffff c05f:TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384:ECDH:ECDSA:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0303:ffff c060:TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256:ECDHE:RSA:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0303:ffff c061:TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384:ECDHE:RSA:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0303:ffff c062:TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256:ECDH:RSA:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0303:ffff c063:TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384:ECDH:RSA:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0303:ffff c064:TLS_PSK_WITH_ARIA_128_CBC_SHA256:PSK:PSK:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0303:ffff c065:TLS_PSK_WITH_ARIA_256_CBC_SHA384:PSK:PSK:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0303:ffff c066:TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256:DHE:PSK:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0303:ffff c067:TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384:DHE:PSK:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0303:ffff c068:TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256:RSA:PSK:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0303:ffff c069:TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384:RSA:PSK:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0303:ffff c06a:TLS_PSK_WITH_ARIA_128_GCM_SHA256:PSK:PSK:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0303:ffff c06b:TLS_PSK_WITH_ARIA_256_GCM_SHA384:PSK:PSK:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0303:ffff c06c:TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256:DHE:PSK:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0303:ffff c06d:TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384:DHE:PSK:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0303:ffff c06e:TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256:RSA:PSK:ARIA:GCM:128:AEAD:128:SHA256:256:rfc6209:0:0303:ffff c06f:TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384:RSA:PSK:ARIA:GCM:256:AEAD:256:SHA384:384:rfc6209:0:0303:ffff c070:TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256:ECDHE:PSK:ARIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6209:0:0303:ffff c071:TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384:ECDHE:PSK:ARIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6209:0:0303:ffff c072:TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:ECDHE:ECDSA:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0303:ffff c073:TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:ECDHE:ECDSA:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0303:ffff c074:TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:ECDH:ECDSA:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0303:ffff c075:TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:ECDH:ECDSA:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0303:ffff c076:TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:ECDHE:RSA:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0303:ffff c077:TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:ECDHE:RSA:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0303:ffff c078:TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:ECDH:RSA:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0303:ffff c079:TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:ECDH:RSA:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0303:ffff c07a:TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:RSA:RSA:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0303:ffff c07b:TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:RSA:RSA:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0303:ffff c07c:TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:DHE:RSA:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0303:ffff c07d:TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:DHE:RSA:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0303:ffff c07e:TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:DH:RSA:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0303:ffff c07f:TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:DH:RSA:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0303:ffff c080:TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:DHE:DSS:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0303:ffff c081:TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:DHE:DSS:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0303:ffff c082:TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:DH:DSS:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0303:ffff c083:TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:DH:DSS:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0303:ffff c084:TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256:DH:NULL:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0303:ffff c085:TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384:DH:NULL:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0303:ffff c086:TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:ECDHE:ECDSA:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0303:ffff c087:TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:ECDHE:ECDSA:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0303:ffff c088:TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:ECDH:ECDSA:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0303:ffff c089:TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:ECDH:ECDSA:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0303:ffff c08a:TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:ECDHE:RSA:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0303:ffff c08b:TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:ECDHE:RSA:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0303:ffff c08c:TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:ECDH:RSA:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0303:ffff c08d:TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:ECDH:RSA:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0303:ffff c08e:TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:PSK:PSK:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0303:ffff c08f:TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:PSK:PSK:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0303:ffff c090:TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:DHE:PSK:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0303:ffff c091:TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:DHE:PSK:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0303:ffff c092:TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:RSA:PSK:CAMELLIA:GCM:128:AEAD:128:SHA256:256:rfc6367:0:0303:ffff c093:TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:RSA:PSK:CAMELLIA:GCM:256:AEAD:256:SHA384:384:rfc6367:0:0303:ffff c094:TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:PSK:PSK:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0303:ffff c095:TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:PSK:PSK:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0303:ffff c096:TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:DHE:PSK:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0303:ffff c097:TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:DHE:PSK:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0303:ffff c098:TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:RSA:PSK:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0303:ffff c099:TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:RSA:PSK:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0303:ffff c09a:TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:ECDHE:PSK:CAMELLIA:CBC:128:HMAC-SHA256:256:SHA256:256:rfc6367:0:0303:ffff c09b:TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:ECDHE:PSK:CAMELLIA:CBC:256:HMAC-SHA384:384:SHA384:384:rfc6367:0:0303:ffff c09c:TLS_RSA_WITH_AES_128_CCM:RSA:RSA:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0303:ffff c09d:TLS_RSA_WITH_AES_256_CCM:RSA:RSA:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0303:ffff c09e:TLS_DHE_RSA_WITH_AES_128_CCM:DHE:RSA:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0303:ffff c09f:TLS_DHE_RSA_WITH_AES_256_CCM:DHE:RSA:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0303:ffff c0a0:TLS_RSA_WITH_AES_128_CCM_8:RSA:RSA:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0303:ffff c0a1:TLS_RSA_WITH_AES_256_CCM_8:RSA:RSA:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0303:ffff c0a2:TLS_DHE_RSA_WITH_AES_128_CCM_8:DHE:RSA:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0303:ffff c0a3:TLS_DHE_RSA_WITH_AES_256_CCM_8:DHE:RSA:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0303:ffff c0a4:TLS_PSK_WITH_AES_128_CCM:PSK:PSK:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0303:ffff c0a5:TLS_PSK_WITH_AES_256_CCM:PSK:PSK:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0303:ffff c0a6:TLS_DHE_PSK_WITH_AES_128_CCM:DHE:PSK:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0303:ffff c0a7:TLS_DHE_PSK_WITH_AES_256_CCM:DHE:PSK:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0303:ffff c0a8:TLS_PSK_WITH_AES_128_CCM_8:PSK:PSK:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0303:ffff c0a9:TLS_PSK_WITH_AES_256_CCM_8:PSK:PSK:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0303:ffff c0aa:TLS_PSK_DHE_WITH_AES_128_CCM_8:PSK:DHE:AES:CCM:128:AEAD:128:DEFAULT:0:rfc6655:0:0303:ffff c0ab:TLS_PSK_DHE_WITH_AES_256_CCM_8:PSK:DHE:AES:CCM:256:AEAD:256:DEFAULT:0:rfc6655:0:0303:ffff c0ac:TLS_ECDHE_ECDSA_WITH_AES_128_CCM:ECDHE:ECDSA:AES:CCM:128:AEAD:128:DEFAULT:0:rfc7251:0:0303:ffff c0ad:TLS_ECDHE_ECDSA_WITH_AES_256_CCM:ECDHE:ECDSA:AES:CCM:256:AEAD:256:DEFAULT:0:rfc7251:0:0303:ffff c0ae:TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:ECDHE:ECDSA:AES:CCM:128:AEAD:128:DEFAULT:0:rfc7251:0:0303:ffff c0af:TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:ECDHE:ECDSA:AES:CCM:256:AEAD:256:DEFAULT:0:rfc7251:0:0303:ffff c0b0:TLS_ECCPWD_WITH_AES_128_GCM_SHA256:ECCPWD:ECCPWD:AES:GCM:128:AEAD:128:SHA256:256:rfc8492:0:0303:ffff c0b1:TLS_ECCPWD_WITH_AES_256_GCM_SHA384:ECCPWD:ECCPWD:AES:GCM:256:AEAD:256:SHA384:384:rfc8492:0:0303:ffff c0b2:TLS_ECCPWD_WITH_AES_128_CCM_SHA256:ECCPWD:ECCPWD:AES:CCM:128:AEAD:128:SHA256:256:rfc8492:0:0303:ffff c0b3:TLS_ECCPWD_WITH_AES_256_CCM_SHA384:ECCPWD:ECCPWD:AES:CCM:256:AEAD:256:SHA384:384:rfc8492:0:0303:ffff c0b4:TLS_SHA256_SHA256:TLS13:TLS13:NULL::0:HMAC-SHA256:256:SHA256:256:draft-camwinget-tls-ts13-macciphersuites:0:0303:ffff c0b5:TLS_SHA384_SHA384:TLS13:TLS13:NULL::0:HMAC-SHA384:384:SHA384:384:draft-camwinget-tls-ts13-macciphersuites:0:0303:ffff cca8:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:ECDHE:RSA:CHACHA20_POLY1305:CBC:256:AEAD:256:SHA256:256:rfc7905:0:0303:ffff cca9:TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:ECDHE:ECDSA:CHACHA20_POLY1305:CBC:256:AEAD:256:SHA256:256:rfc7905:0:0303:ffff ccaa:TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:DHE:RSA:CHACHA20_POLY1305:CBC:256:AEAD:256:SHA256:256:rfc7905:0:0303:ffff ccab:TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:PSK:PSK:CHACHA20_POLY1305:CBC:256:AEAD:256:SHA256:256:rfc7905:0:0303:ffff ccac:TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:ECDHE:PSK:CHACHA20_POLY1305:CBC:256:AEAD:256:SHA256:256:rfc7905:0:0303:ffff ccad:TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:DHE:PSK:CHACHA20_POLY1305:CBC:256:AEAD:256:SHA256:256:rfc7905:0:0303:ffff ccae:TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256:RSA:PSK:CHACHA20_POLY1305:CBC:256:AEAD:256:SHA256:256:rfc7905:0:0303:ffff d001:TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256:ECDHE:PSK:AES:GCM:128:AEAD:128:SHA256:256:rfc8442:0:0303:ffff d002:TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384:ECDHE:PSK:AES:GCM:256:AEAD:256:SHA384:384:rfc8442:0:0303:ffff d003:TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256:ECDHE:PSK:AES:CCM:128:AEAD:128:SHA256:256:rfc8442:0:0303:ffff d005:TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256:ECDHE:PSK:AES:CCM:128:AEAD:128:SHA256:256:rfc8442:0:0303:ffff tls-parser-0.9.2/src/lib.rs010064400017500001750000000136521351777233400137650ustar0000000000000000//! # 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. //! //! 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 //! extern crate nom; //! extern crate tls_parser; //! //! use nom::{Err, IResult}; //! use tls_parser::parse_tls_plaintext; //! //! # fn main() { //! 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 //! # extern crate nom; //! # extern crate tls_parser; //! # use nom::{Err, IResult}; //! # use tls_parser::{parse_tls_raw_record, parse_tls_record_with_header}; //! //! # fn main() { //! # 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 //! # extern crate nom; //! # extern crate tls_parser; //! # use nom::{Err, IResult}; //! # use tls_parser::{tls_state_transition, TlsMessage, TlsState}; //! //! 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,*/unsafe_code, unstable_features, /*unused_import_braces,*/ unused_qualifications)] #[macro_use] extern crate enum_primitive; #[macro_use] extern crate nom; extern crate phf; #[macro_use] extern crate rusticata_macros; #[cfg(feature = "serialize")] extern crate cookie_factory; pub use tls_alert::*; /// TLS alerts #[macro_use] pub mod tls_alert; pub use tls_ciphers::*; /// TLS ciphersuites definitions and parameters pub mod tls_ciphers; pub use tls_dh::*; /// Diffie-Hellman parameters pub mod tls_dh; pub use tls_ec::*; /// Elliptic curves pub mod tls_ec; pub use tls_extensions::*; /// TLS extensions #[macro_use] pub mod tls_extensions; pub use tls_sign_hash::*; /// TLS signature schemes pub mod tls_sign_hash; pub use tls_states::*; /// TLS state machine pub mod tls_states; pub use tls::*; /// TLS parser structures and functions pub mod tls; mod tls_debug; pub mod tls_serialize; pub use tls_serialize::*; tls-parser-0.9.2/src/tls.rs010064400017500001750000000713411351777430200140150ustar0000000000000000//! # TLS parser //! Parsing functions for the TLS protocol, supporting versions 1.0 to 1.3 use nom::combinator::rest; use nom::error::ErrorKind; use nom::number::streaming::{be_u16, be_u24, be_u32, be_u8}; use nom::{Err, IResult}; use crate::tls_alert::*; use crate::tls_ciphers::*; use crate::tls_ec::ECPoint; use std::convert::AsRef; use std::fmt; use std::ops::Deref; /// 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)] pub struct TlsHandshakeType(pub u8); newtype_enum! { impl debug TlsHandshakeType { HelloRequest = 0x00, ClientHello = 0x01, ServerHello = 0x02, 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 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)] 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, } } impl From 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)] pub struct TlsHeartbeatMessageType(pub u8); newtype_enum! { impl debug TlsHeartbeatMessageType { HeartBeatRequest = 0x1, HeartBeatResponse = 0x2, } } impl From for u8 { fn from(v: TlsHeartbeatMessageType) -> u8 { v.0 } } /// Content type, as defined in IANA TLS ContentType registry #[derive(Clone, Copy, PartialEq, Eq)] pub struct TlsRecordType(pub u8); newtype_enum! { impl debug TlsRecordType { ChangeCipherSpec = 0x14, Alert = 0x15, Handshake = 0x16, ApplicationData = 0x17, Heartbeat = 0x18, } } impl From for u8 { fn from(v: TlsRecordType) -> u8 { v.0 } } #[derive(Clone, Copy, PartialEq, Eq)] pub struct TlsCompressionID(pub u8); newtype_enum! { impl debug TlsCompressionID { Null = 0x00, } } impl From 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 for TlsCompressionID { fn as_ref(&self) -> &u8 { &self.0 } } #[derive(Clone, Copy, PartialEq, Eq)] pub struct TlsCipherSuiteID(pub u16); impl TlsCipherSuiteID { pub fn get_ciphersuite(&self) -> Option<&'static TlsCipherSuite> { TlsCipherSuite::from_id(self.0) } } impl From 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 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(ref 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) } } /// 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, /// A list of compression methods supported by client pub comp: Vec, 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, co: Vec, 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> { self.ciphers.iter().map(|&x| x.get_ciphersuite()).collect() } } /// 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>, } /// 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, pub sig_hash_algs: Option>, /// 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)] 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>, } /// 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], } fn parse_cipher_suites(i: &[u8], len: usize) -> IResult<&[u8], Vec> { if len == 0 { return Ok((i, Vec::new())); } if len % 2 == 1 || len > i.len() { return Err(Err::Error(error_position!(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)) } fn parse_compressions_algs(i: &[u8], len: usize) -> IResult<&[u8], Vec> { if len == 0 { return Ok((i, Vec::new())); } if len > i.len() { return Err(Err::Error(error_position!(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> { let len = i.len(); if len == 0 { return Ok((i, Vec::new())); } if len % 2 == 1 || len > i.len() { return Err(Err::Error(error_position!(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)) } named! {parse_certs>, many0!( complete!( map!( length_data!(be_u24), |s| RawCertificate{ data: s } ) ) ) } named! {parse_tls_record_header, do_parse!( t: be_u8 >> v: be_u16 >> l: be_u16 >> ( TlsRecordHeader { record_type: TlsRecordType(t), version: TlsVersion(v), len: l, } ) ) } named!( parse_tls_handshake_msg_hello_request, value!(TlsMessageHandshake::HelloRequest) ); named! {parse_tls_handshake_msg_client_hello, do_parse!( v: be_u16 >> rand_time: be_u32 >> rand_data: take!(28) >> // 28 as 32 (aligned) - 4 (time) sidlen: be_u8 >> // check <= 32, can be 0 error_if!(sidlen > 32, ErrorKind::Verify) >> sid: cond!(sidlen > 0, take!(sidlen as usize)) >> ciphers_len: be_u16 >> ciphers: call!(parse_cipher_suites, ciphers_len as usize) >> comp_len: be_u8 >> comp: call!(parse_compressions_algs, comp_len as usize) >> ext: opt!(complete!(length_data!(be_u16))) >> ( TlsMessageHandshake::ClientHello( TlsClientHelloContents::new(v,rand_time,rand_data,sid,ciphers,comp.to_vec(),ext) ) ) ) } named! {parse_tls_handshake_msg_server_hello_tlsv12, do_parse!( v: be_u16 >> rand_time: be_u32 >> rand_data: take!(28) >> // 28 as 32 (aligned) - 4 (time) sidlen: be_u8 >> // check <= 32, can be 0 error_if!(sidlen > 32, ErrorKind::Verify) >> sid: cond!(sidlen > 0, take!(sidlen as usize)) >> cipher: be_u16 >> comp: be_u8 >> ext: opt!(complete!(length_data!(be_u16))) >> ( TlsMessageHandshake::ServerHello( TlsServerHelloContents::new(v,rand_time,rand_data,sid,cipher,comp,ext) ) ) ) } named! {parse_tls_handshake_msg_server_hello_tlsv13draft18, do_parse!( hv: be_u16 >> random: take!(32) >> cipher: be_u16 >> ext: opt!(complete!(length_data!(be_u16))) >> ( TlsMessageHandshake::ServerHelloV13Draft18( TlsServerHelloV13Draft18Contents { version: TlsVersion(hv), random: random, cipher: TlsCipherSuiteID(cipher), ext: ext, } ) ) ) } fn parse_tls_handshake_msg_server_hello(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> { let (_, version) = peek!(i, call!(be_u16))?; 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(error_position!(i, ErrorKind::Tag))), } } // RFC 5077 Stateless TLS Session Resumption fn parse_tls_handshake_msg_newsessionticket( i: &[u8], len: usize, ) -> IResult<&[u8], TlsMessageHandshake> { do_parse!( i, hint: be_u32 >> raw: take!(len - 4) >> (TlsMessageHandshake::NewSessionTicket(TlsNewSessionTicketContent { ticket_lifetime_hint: hint, ticket: raw, })) ) } named! {parse_tls_handshake_msg_hello_retry_request, do_parse!( hv: be_u16 >> c: be_u16 >> ext: opt!(complete!(length_data!(be_u16))) >> ( TlsMessageHandshake::HelloRetryRequest( TlsHelloRetryRequestContents { version: TlsVersion(hv), cipher: TlsCipherSuiteID(c), ext: ext, } ) ) ) } named! {parse_tls_handshake_msg_certificate, do_parse!( cert_len: be_u24 >> certs: flat_map!(take!(cert_len),parse_certs) >> ( TlsMessageHandshake::Certificate( TlsCertificateContents { cert_chain: certs, } ) ) ) } fn parse_tls_handshake_msg_serverkeyexchange( i: &[u8], len: usize, ) -> IResult<&[u8], TlsMessageHandshake> { map!(i, take!(len), |ext| { TlsMessageHandshake::ServerKeyExchange(TlsServerKeyExchangeContents { parameters: ext }) }) } fn parse_tls_handshake_msg_serverdone(i: &[u8], len: usize) -> IResult<&[u8], TlsMessageHandshake> { map!(i, take!(len), |ext| { TlsMessageHandshake::ServerDone(ext) }) } fn parse_tls_handshake_msg_certificateverify( i: &[u8], len: usize, ) -> IResult<&[u8], TlsMessageHandshake> { map!(i, take!(len), |blob| { TlsMessageHandshake::CertificateVerify(blob) }) } fn parse_tls_handshake_msg_clientkeyexchange( i: &[u8], len: usize, ) -> IResult<&[u8], TlsMessageHandshake> { map!(i, take!(len), |ext| { TlsMessageHandshake::ClientKeyExchange(TlsClientKeyExchangeContents::Unknown(ext)) }) } fn parse_certrequest_nosigalg(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> { do_parse! { i, cert_types: length_count!(be_u8,be_u8) >> ca_len: be_u16 >> ca: flat_map!(take!(ca_len),many0!(complete!(length_data!(be_u16)))) >> ( TlsMessageHandshake::CertificateRequest( TlsCertificateRequestContents { cert_types: cert_types, // sig_hash_algs: Some(sig_hash_algs), sig_hash_algs: None, unparsed_ca: ca, } ) ) } } fn parse_certrequest_full(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> { do_parse! { i, cert_types: length_count!(be_u8,be_u8) >> sig_hash_algs_len: be_u16 >> sig_hash_algs: flat_map!(take!(sig_hash_algs_len),many0!(complete!(be_u16))) >> ca_len: be_u16 >> ca: flat_map!(take!(ca_len),many0!(complete!(length_data!(be_u16)))) >> ( TlsMessageHandshake::CertificateRequest( TlsCertificateRequestContents { cert_types: cert_types, sig_hash_algs: Some(sig_hash_algs), unparsed_ca: ca, } ) ) } } #[inline] fn parse_tls_handshake_msg_certificaterequest(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> { alt!( i, complete!(parse_certrequest_full) | complete!(parse_certrequest_nosigalg) ) } fn parse_tls_handshake_msg_finished(i: &[u8], len: usize) -> IResult<&[u8], TlsMessageHandshake> { map!(i, take!(len), |blob| { TlsMessageHandshake::Finished(blob) }) } // 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. named! {parse_tls_handshake_msg_certificatestatus, do_parse!( status_type: be_u8 >> blob: length_data!(be_u24) >> ( TlsMessageHandshake::CertificateStatus( TlsCertificateStatusContents{ status_type:status_type, blob:blob, } ) ) ) } /// 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> { do_parse! { i, selected_protocol: length_data!(be_u8) >> padding: length_data!(be_u8) >> ( TlsMessageHandshake::NextProtocol( TlsNextProtocolContent { selected_protocol: selected_protocol, padding: padding, } ) ) } } fn parse_tls_handshake_msg_key_update(i: &[u8]) -> IResult<&[u8], TlsMessageHandshake> { map!(i, be_u8, |update_request| { TlsMessageHandshake::KeyUpdate(update_request) }) } named! {parse_tls_message_handshake, do_parse!( ht: be_u8 >> hl: be_u24 >> m: flat_map!(take!(hl), switch!(value!(ht), /*TlsHandshakeType::HelloRequest*/ 0x00 => call!(parse_tls_handshake_msg_hello_request) | /*TlsHandshakeType::ClientHello*/ 0x01 => call!(parse_tls_handshake_msg_client_hello) | /*TlsHandshakeType::ServerHello*/ 0x02 => call!(parse_tls_handshake_msg_server_hello) | /*TlsHandshakeType::NewSessionTicket*/ 0x04 => call!(parse_tls_handshake_msg_newsessionticket,hl as usize) | /*TlsHandshakeType::EndOfEarlyData*/ 0x05 => value!(TlsMessageHandshake::EndOfEarlyData) | /*TlsHandshakeType::HelloRetryRequest*/ 0x06 => call!(parse_tls_handshake_msg_hello_retry_request) | /*TlsHandshakeType::Certificate*/ 0x0b => call!(parse_tls_handshake_msg_certificate) | /*TlsHandshakeType::ServerKeyExchange*/ 0x0c => call!(parse_tls_handshake_msg_serverkeyexchange,hl as usize) | /*TlsHandshakeType::CertificateRequest*/ 0x0d => call!(parse_tls_handshake_msg_certificaterequest) | /*TlsHandshakeType::ServerDone*/ 0x0e => call!(parse_tls_handshake_msg_serverdone,hl as usize) | /*TlsHandshakeType::CertificateVerify*/ 0x0f => call!(parse_tls_handshake_msg_certificateverify,hl as usize) | /*TlsHandshakeType::ClientKeyExchange*/ 0x10 => call!(parse_tls_handshake_msg_clientkeyexchange,hl as usize) | /*TlsHandshakeType::Finished*/ 0x14 => call!(parse_tls_handshake_msg_finished,hl as usize) | /*TlsHandshakeType::CertificateURL*/ /*0x15 => call!(parse_tls_handshake_msg_certificateurl) |*/ /*TlsHandshakeType::CertificateStatus*/ 0x16 => call!(parse_tls_handshake_msg_certificatestatus) | /*TlsHandshakeType::KeyUpdate*/ 0x18 => call!(parse_tls_handshake_msg_key_update) | /*TlsHandshakeType::NextProtocol*/ 0x43 => call!(parse_tls_handshake_msg_next_protocol) ) ) >> ( TlsMessage::Handshake(m) ) ) } // XXX add extra verification hdr.len == 1 named!( parse_tls_message_changecipherspec, map!(tag!([0x01]), |_| { TlsMessage::ChangeCipherSpec }) ); // XXX add extra verification hdr.len == 2 named! {parse_tls_message_alert, do_parse!( s: be_u8 >> c: be_u8 >> ( TlsMessage::Alert( TlsMessageAlert { severity: TlsAlertSeverity(s), code: TlsAlertDescription(c), } ) ) ) } fn parse_tls_message_applicationdata(i: &[u8]) -> IResult<&[u8], TlsMessage> { map!(i, rest, |b| { TlsMessage::ApplicationData(TlsMessageApplicationData { blob: b }) }) } fn parse_tls_message_heartbeat( i: &[u8], tls_plaintext_len: u16, ) -> IResult<&[u8], Vec> { do_parse! {i, hb_type: be_u8 >> hb_len: be_u16 >> error_if!(tls_plaintext_len < 3, ErrorKind::Verify) >> b: take!(tls_plaintext_len - 3) >> // payload (hb_len) + padding ( vec![TlsMessage::Heartbeat( TlsMessageHeartbeat { heartbeat_type: TlsHeartbeatMessageType(hb_type), payload_len: hb_len, payload: b, } )] ) } } /// 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] pub fn parse_tls_record_with_header<'i, 'hdr>(i:&'i [u8], hdr:&'hdr TlsRecordHeader ) -> IResult<&'i [u8], Vec>> { match hdr.record_type { TlsRecordType::ChangeCipherSpec => many1!(i, complete!(parse_tls_message_changecipherspec)), TlsRecordType::Alert => many1!(i, complete!(parse_tls_message_alert)), TlsRecordType::Handshake => many1!(i, complete!(parse_tls_message_handshake)), TlsRecordType::ApplicationData => many1!(i, complete!(parse_tls_message_applicationdata)), TlsRecordType::Heartbeat => parse_tls_message_heartbeat(i, hdr.len), _ => Err(Err::Error(error_position!(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> { do_parse! { i, hdr: parse_tls_record_header >> error_if!(hdr.len > MAX_RECORD_LEN, ErrorKind::TooLarge) >> msg: flat_map!(take!(hdr.len), call!(parse_tls_record_with_header, &hdr) ) >> ( TlsPlaintext { hdr, msg } ) } } /// Parse one packet only, as encrypted content pub fn parse_tls_encrypted(i: &[u8]) -> IResult<&[u8], TlsEncrypted> { do_parse! { i, hdr: parse_tls_record_header >> error_if!(hdr.len > MAX_RECORD_LEN, ErrorKind::TooLarge) >> blob: take!(hdr.len) >> ( TlsEncrypted { hdr, msg:TlsEncryptedContent{ blob } } ) } } /// 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> { do_parse! { i, hdr: parse_tls_record_header >> error_if!(hdr.len > MAX_RECORD_LEN, ErrorKind::TooLarge) >> data: take!(hdr.len) >> ( 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. 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> { many1!(i, complete!(parse_tls_plaintext)) } tls-parser-0.9.2/src/tls_alert.rs010064400017500001750000000054311355234366100152000ustar0000000000000000/// TLS alert severity #[derive(Clone, Copy, Debug, PartialEq, Eq)] 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)] pub struct TlsAlertDescription(pub u8); newtype_enum! { impl display TlsAlertDescription { CloseNotify = 0x00, EndOfEarlyData = 0x01, 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)] 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 tls-parser-0.9.2/src/tls_ciphers.rs010064400017500001750000000061151356670714600155350ustar0000000000000000//! //! 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)] use phf; enum_from_primitive! { /// Key exchange methods #[derive(Clone,Debug,PartialEq)] #[repr(u8)] pub enum TlsCipherKx { Null = 0, Psk, Krb5, Srp, Rsa, Dh, Dhe, Ecdh, Ecdhe, Eccpwd, Tls13, } } enum_from_primitive! { /// Authentication methods #[derive(Clone,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,Debug,PartialEq)] #[repr(u8)] pub enum TlsCipherEnc { Null, Des, TripleDes, Rc2, Rc4, Aria, Idea, Seed, Aes, Camellia, Chacha20_Poly1305, } } enum_from_primitive! { /// Encryption modes #[derive(Clone,Debug,PartialEq)] #[repr(u8)] pub enum TlsCipherEncMode { Null, Cbc, Ccm, Gcm, } } enum_from_primitive! { /// Message Authentication Code (MAC) methods #[derive(Clone,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.len() > 0); } #[test] fn test_cipher_from_id() { match TlsCipherSuite::from_id(0xc025) { Some(ref cipher) => { println!("Found cipher: {:?}", cipher); } None => assert!(false), } } #[test] fn test_cipher_from_name() { match TlsCipherSuite::from_name("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384") { Some(ref cipher) => { println!("Found cipher: {:?}", cipher); } None => assert!(false), } } #[test] fn test_cipher_filter() { let ecdhe_ciphers: Vec<&TlsCipherSuite> = CIPHERS .values() .filter(|c| c.kx == TlsCipherKx::Ecdhe) .collect(); assert!(ecdhe_ciphers.len() > 20); } } tls-parser-0.9.2/src/tls_debug.rs010064400017500001750000000263711351777443100151710ustar0000000000000000use std::fmt; use std::str::from_utf8; use rusticata_macros::debug::HexSlice; use crate::tls::*; use crate::tls_alert::*; use crate::tls_dh::*; use crate::tls_ec::*; use crate::tls_extensions::*; use crate::tls_sign_hash::*; // ------------------------- 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(ref p) => { fmt.write_fmt(format_args!("{:?}", HexSlice(p))) } &TlsClientKeyExchangeContents::Ecdh(ref p) => fmt.write_fmt(format_args!("{:?}", p)), &TlsClientKeyExchangeContents::Unknown(ref 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(""); 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| { let s = from_utf8(c).unwrap_or(""); format!("{}", s) }) .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() } } tls-parser-0.9.2/src/tls_dh.rs010064400017500001750000000012741351777446300144760ustar0000000000000000use nom::number::streaming::be_u16; /// Diffie-Hellman parameters, defined in [RFC5246] section 7.4.3 #[derive(PartialEq)] pub struct ServerDHParams<'a> { /// The prime modulus used for the Diffie-Hellman operation. pub dh_p: &'a [u8], /// The generator used for the Diffie-Hellman operation. pub dh_g: &'a [u8], /// The server's Diffie-Hellman public value (g^X mod p). pub dh_ys: &'a [u8], } named! {pub parse_dh_params, do_parse!( p: length_data!(be_u16) >> g: length_data!(be_u16) >> ys: length_data!(be_u16) >> ( ServerDHParams{ dh_p: p, dh_g: g, dh_ys: ys, }) ) } tls-parser-0.9.2/src/tls_ec.rs010064400017500001750000000153121351777461100144630ustar0000000000000000use nom::error::ErrorKind; use nom::number::streaming::{be_u16, be_u8}; use nom::{Err, IResult}; /// 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)] 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, 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 { 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)] pub struct ECCurve<'a> { pub a: &'a [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)] pub struct ECCurveType(pub u8); newtype_enum! { impl display ECCurveType { ExplicitPrime = 1, ExplicitChar2 = 2, NamedGroup = 3, } } /// EC Point #[derive(Clone, Debug, PartialEq)] pub struct ECPoint<'a> { 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)] pub struct ExplicitPrimeContent<'a> { pub prime_p: &'a [u8], pub curve: ECCurve<'a>, pub base: ECPoint<'a>, pub order: &'a [u8], pub cofactor: &'a [u8], } /// Elliptic curve parameters content (depending on EC type) #[derive(PartialEq)] pub enum ECParametersContent<'a> { ExplicitPrime(ExplicitPrimeContent<'a>), // TODO ExplicitChar2 is defined in [RFC4492] section 5.4 ExplicitChar2(&'a [u8]), NamedGroup(NamedGroup), } /// Elliptic curve parameters, /// defined in [RFC4492](https://tools.ietf.org/html/rfc4492) section 5.4 #[derive(PartialEq)] pub struct ECParameters<'a> { /// Should match a [ECCurveType](enum.ECCurveType.html) value pub curve_type: ECCurveType, pub params_content: ECParametersContent<'a>, } /// ECDH parameters /// defined in [RFC4492](https://tools.ietf.org/html/rfc4492) section 5.4 #[derive(Debug, PartialEq)] 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> { let len = i.len(); if len == 0 { return Ok((i, Vec::new())); } if len % 2 == 1 || len > i.len() { return Err(Err::Error(error_position!(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)) } named!( parse_ec_point, map!(length_data!(be_u8), |d| { ECPoint { point: d } }) ); named! {parse_ec_curve, do_parse!( a: length_data!(be_u8) >> b: length_data!(be_u8) >> ( ECCurve{a:a,b:b} ) ) } named! {parse_ec_explicit_prime_content, do_parse!( p: length_data!(be_u8) >> curve: parse_ec_curve >> base: parse_ec_point >> order: length_data!(be_u8) >> cofactor: length_data!(be_u8) >> ( ECParametersContent::ExplicitPrime( ExplicitPrimeContent{ prime_p: p, curve: curve, base: base, order: order, cofactor: cofactor, } ) ) ) } named!( parse_ec_named_curve_content, map!(be_u16, |c| { ECParametersContent::NamedGroup(NamedGroup(c)) }) ); named! {pub parse_ec_parameters, do_parse!( curve_type: be_u8 >> d: switch!(value!(curve_type), 1 => call!(parse_ec_explicit_prime_content) | 3 => call!(parse_ec_named_curve_content) ) >> ( ECParameters{ curve_type: ECCurveType(curve_type), params_content: d, } ) ) } named! {pub parse_ecdh_params, do_parse!( c: parse_ec_parameters >> p: parse_ec_point >> ( ServerECDHParams{curve_params:c,public:p} ) ) } tls-parser-0.9.2/src/tls_extensions.rs010064400017500001750000000554101352002546300162620ustar0000000000000000//! //! 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 nom::error::ErrorKind; use nom::number::streaming::{be_u16, be_u32, be_u8}; use nom::IResult; use std::convert::From; use crate::tls::{parse_tls_versions, TlsCipherSuiteID, TlsVersion}; use crate::tls_ec::{parse_named_groups, NamedGroup}; /// 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)] pub struct TlsExtensionType(pub u16); newtype_enum! { impl display TlsExtensionType { ServerName = 0x0000, // [RFC6066] MaxFragmentLength = 0x0001, ClientCertificate = 0x0002, TrustedCaKeys = 0x0003, TruncatedHMac = 0x0004, StatusRequest = 0x0005, // [RFC6066] UserMapping = 0x0006, ClientAuthz = 0x0007, ServerAuthz = 0x0008, CertType = 0x0009, SupportedGroups = 0x000a, // [RFC4492][RFC7919] EcPointFormats = 0x000b, // [RFC4492] Srp = 0x000c, // [RFC5054] SignatureAlgorithms = 0x000d, UseSrtp = 0x000e, Heartbeat = 0x000f, ApplicationLayerProtocolNegotiation = 0x0010, // [RFC7301] StatusRequestv2 = 0x0011, SignedCertificateTimestamp = 0x0012, ClientCertificateType = 0x0013, ServerCertificateType = 0x0014, Padding = 0x0015, // [RFC7685] EncryptThenMac = 0x0016, ExtendedMasterSecret = 0x0017, TokenBinding = 0x0018, CachedInfo = 0x0019, RecordSizeLimit = 0x001c, // [RFC8449] SessionTicketTLS = 0x0023, KeyShareOld = 0x0028, // move to 51 in TLS 1.3 draft 23 PreSharedKey = 0x0029, EarlyData = 0x002a, SupportedVersions = 0x002b, Cookie = 0x002c, PskExchangeModes = 0x002d, TicketEarlyDataInfo = 0x002e, // TLS 1.3 draft 18, removed in draft 19 CertificateAuthorities = 0x002f, OidFilters = 0x0030, PostHandshakeAuth = 0x0031, // TLS 1.3 draft 20 SigAlgorithmsCert = 0x0032, // TLS 1.3 draft 23 KeyShare = 0x0033, // TLS 1.3 draft 23 NextProtocolNegotiation = 0x3374, Grease = 0xfafa, RenegotiationInfo = 0xff01, EncryptedServerName = 0xffce, // draft-ietf-tls-esni } } impl TlsExtensionType { pub fn from_u16(t: u16) -> TlsExtensionType { TlsExtensionType(t) } } impl From 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), EcPointFormats(&'a [u8]), SignatureAlgorithms(Vec), RecordSizeLimit(u16), SessionTicket(&'a [u8]), KeyShareOld(&'a [u8]), KeyShare(&'a [u8]), PreSharedKey(&'a [u8]), EarlyData(Option), SupportedVersions(Vec), Cookie(&'a [u8]), PskExchangeModes(Vec), Heartbeat(u8), ALPN(Vec<&'a [u8]>), SignedCertificateTimestamp(Option<(&'a [u8])>), Padding(&'a [u8]), EncryptThenMac, ExtendedMasterSecret, OidFilters(Vec>), 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)] pub struct PskKeyExchangeMode(pub u8); newtype_enum! { impl PskKeyExchangeMode { Psk = 0, PskDhe = 1, } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct SNIType(pub u8); newtype_enum! { impl display SNIType { HostName = 0, } } #[derive(Clone, Copy, PartialEq, Eq)] 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], } named! {pub parse_tls_extension_sni_hostname<(SNIType,&[u8])>, do_parse!( t: be_u8 >> v: length_data!(be_u16) >> ( SNIType(t), v ) ) } named! {pub parse_tls_extension_sni_content, do_parse!( list_len: be_u16 >> v: flat_map!(take!(list_len), many0!(complete!(parse_tls_extension_sni_hostname)) ) >> ( TlsExtension::SNI(v) ) ) } named! {pub parse_tls_extension_sni, do_parse!( tag!([0x00,0x00]) >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),parse_tls_extension_sni_content) >> ( ext ) ) } /// Max fragment length [RFC6066] pub fn parse_tls_extension_max_fragment_length_content(i: &[u8]) -> IResult<&[u8], TlsExtension> { map!(i, be_u8, |l| { TlsExtension::MaxFragmentLength(l) }) } /// Max fragment length [RFC6066] pub fn parse_tls_extension_max_fragment_length(i: &[u8]) -> IResult<&[u8], TlsExtension> { do_parse! { i, tag!([0x00,0x01]) >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),parse_tls_extension_max_fragment_length_content) >> ( ext ) } } /// 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))), _ => { do_parse! { i, status_type: be_u8 >> request: take!(ext_len-1) >> ( TlsExtension::StatusRequest(Some((CertificateStatusType(status_type),request))) ) } } } } named! {pub parse_tls_extension_status_request, do_parse!( tag!([0x00,0x05]) >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),call!(parse_tls_extension_status_request_content,ext_len)) >> ( ext ) ) } named! {pub parse_tls_extension_elliptic_curves_content, flat_map!( length_data!(be_u16), map!(parse_named_groups, |x| TlsExtension::EllipticCurves(x)) ) } named! {pub parse_tls_extension_elliptic_curves, do_parse!( tag!([0x00,0x0a]) >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),parse_tls_extension_elliptic_curves_content) >> ( ext ) ) } named! {pub parse_tls_extension_ec_point_formats_content, map!( length_data!(be_u8), |v| { TlsExtension::EcPointFormats(v) } ) } named! {pub parse_tls_extension_ec_point_formats, do_parse!( tag!([0x00,0x0b]) >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),parse_tls_extension_ec_point_formats_content) >> ( ext ) ) } named! {pub parse_tls_extension_signature_algorithms_content, do_parse!( list_len: be_u16 >> l: flat_map!(take!(list_len), many0!(complete!(be_u16)) ) >> ( TlsExtension::SignatureAlgorithms(l) ) // XXX SignatureAlgorithms or SignatureScheme ) } named! {pub parse_tls_extension_signature_algorithms, do_parse!( tag!([0x00,0x0d]) >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),parse_tls_extension_signature_algorithms_content) >> ( ext ) ) } named! {pub parse_tls_extension_heartbeat_content, map!( be_u8, |hb_mode| { TlsExtension::Heartbeat(hb_mode) } ) } named! {pub parse_tls_extension_heartbeat, do_parse!( tag!([0x00,0x0f]) >> ext_len: be_u16 >> error_if!(ext_len != 1, ErrorKind::Verify) >> ext: flat_map!(take!(ext_len),parse_tls_extension_heartbeat_content) >> ( ext ) ) } named!(parse_protocol_name<&[u8]>, length_data!(be_u8)); /// Defined in [RFC7301] pub fn parse_tls_extension_alpn_content(i: &[u8]) -> IResult<&[u8], TlsExtension> { do_parse! { i, list_len: be_u16 >> v: flat_map!(take!(list_len),many0!(complete!(parse_protocol_name))) >> ( TlsExtension::ALPN(v) ) } } /// Defined in [RFC7685] fn parse_tls_extension_padding_content(i: &[u8], ext_len: u16) -> IResult<&[u8], TlsExtension> { map!(i, take!(ext_len), |d| { TlsExtension::Padding(d) }) } /// Defined in [RFC6962] pub fn parse_tls_extension_signed_certificate_timestamp_content( i: &[u8], ) -> IResult<&[u8], TlsExtension> { map!(i, opt!(complete!(length_data!(be_u16))), |d| { TlsExtension::SignedCertificateTimestamp(d) }) } /// Encrypt-then-MAC is defined in [RFC7366] fn parse_tls_extension_encrypt_then_mac_content( i: &[u8], ext_len: u16, ) -> IResult<&[u8], TlsExtension> { do_parse! { i, error_if!(ext_len != 0, ErrorKind::Verify) >> ( TlsExtension::EncryptThenMac ) } } /// Encrypt-then-MAC is defined in [RFC7366] pub fn parse_tls_extension_encrypt_then_mac(i: &[u8]) -> IResult<&[u8], TlsExtension> { do_parse! { i, tag!([0x00,0x16]) >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),call!(parse_tls_extension_encrypt_then_mac_content,ext_len)) >> ( ext ) } } /// Extended Master Secret is defined in [RFC7627] fn parse_tls_extension_extended_master_secret_content( i: &[u8], ext_len: u16, ) -> IResult<&[u8], TlsExtension> { do_parse! { i, error_if!(ext_len != 0, ErrorKind::Verify) >> ( TlsExtension::ExtendedMasterSecret ) } } /// Extended Master Secret is defined in [RFC7627] fn parse_tls_extension_record_size_limit(i: &[u8]) -> IResult<&[u8], TlsExtension> { do_parse! { i, limit: be_u16 >> ( TlsExtension::RecordSizeLimit(limit) ) } } /// Extended Master Secret is defined in [RFC7627] pub fn parse_tls_extension_extended_master_secret(i: &[u8]) -> IResult<&[u8], TlsExtension> { do_parse! { i, tag!([0x00,0x17]) >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),call!(parse_tls_extension_extended_master_secret_content,ext_len)) >> ( ext ) } } fn parse_tls_extension_session_ticket_content( i: &[u8], ext_len: u16, ) -> IResult<&[u8], TlsExtension> { map!(i, take!(ext_len), |ext_data| { TlsExtension::SessionTicket(ext_data) }) } named! {pub parse_tls_extension_session_ticket, do_parse!( tag!([0x00,0x23]) >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),call!(parse_tls_extension_session_ticket_content,ext_len)) >> ( ext ) ) } fn parse_tls_extension_key_share_old_content( i: &[u8], ext_len: u16, ) -> IResult<&[u8], TlsExtension> { map!(i, take!(ext_len), |ext_data| { TlsExtension::KeyShareOld(ext_data) }) } fn parse_tls_extension_key_share_content(i: &[u8], ext_len: u16) -> IResult<&[u8], TlsExtension> { map!(i, take!(ext_len), |ext_data| { TlsExtension::KeyShare(ext_data) }) } named! {pub parse_tls_extension_key_share, do_parse!( tag!([0x00,0x33]) >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),call!(parse_tls_extension_key_share_content,ext_len)) >> ( ext ) ) } fn parse_tls_extension_pre_shared_key_content( i: &[u8], ext_len: u16, ) -> IResult<&[u8], TlsExtension> { map!(i, take!(ext_len), |ext_data| { TlsExtension::PreSharedKey(ext_data) }) } named!(pub parse_tls_extension_pre_shared_key, do_parse!( tag!([0x00,0x28]) >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),call!(parse_tls_extension_pre_shared_key_content,ext_len)) >> ( ext ) ) ); fn parse_tls_extension_early_data_content(i: &[u8], ext_len: u16) -> IResult<&[u8], TlsExtension> { do_parse! { i, o: cond!(ext_len > 0, be_u32) >> ( TlsExtension::EarlyData(o) ) } } named! {pub parse_tls_extension_early_data, do_parse!( tag!([0x00,0x2a]) >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),call!(parse_tls_extension_early_data_content,ext_len)) >> ( ext ) ) } // 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!(i, be_u16, |x| TlsExtension::SupportedVersions(vec![ TlsVersion(x) ])) } else { do_parse! { i, _n: be_u8 >> // l: flat_map!(take!(ext_len-1),many0!(complete!(be_u16))) >> l: flat_map!(take!(ext_len-1),parse_tls_versions) >> ( TlsExtension::SupportedVersions(l) ) } } } named! {pub parse_tls_extension_supported_versions, do_parse!( tag!([0x00,0x2b]) >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),call!(parse_tls_extension_supported_versions_content,ext_len)) >> ( ext ) ) } fn parse_tls_extension_cookie_content(i: &[u8], ext_len: u16) -> IResult<&[u8], TlsExtension> { map!(i, take!(ext_len), |ext_data| { TlsExtension::Cookie(ext_data) }) } named! {pub parse_tls_extension_cookie, do_parse!( tag!([0x00,0x2c]) >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),call!(parse_tls_extension_cookie_content,ext_len)) >> ( ext ) ) } named! {pub parse_tls_extension_psk_key_exchange_modes_content, do_parse!( l: be_u8 >> v: take!(l) >> ( TlsExtension::PskExchangeModes(v.to_vec()) ) ) } named! {pub parse_tls_extension_psk_key_exchange_modes, do_parse!( tag!([0x00,0x2d]) >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),call!(parse_tls_extension_psk_key_exchange_modes_content)) >> ( ext ) ) } /// 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> { do_parse! { i, error_if!(ext_len != 0, ErrorKind::Verify) >> ( TlsExtension::NextProtocolNegotiation ) } } /// Renegotiation Info, defined in [RFC5746] pub fn parse_tls_extension_renegotiation_info_content(i: &[u8]) -> IResult<&[u8], TlsExtension> { do_parse! { i, reneg_info_len: be_u8 >> reneg_info : take!(reneg_info_len) >> ( TlsExtension::RenegotiationInfo(reneg_info) ) } } /// Encrypted Server Name, defined in [draft-ietf-tls-esni] pub fn parse_tls_extension_encrypted_server_name(i: &[u8]) -> IResult<&[u8], TlsExtension> { do_parse! { i, ciphersuite: be_u16 >> group: be_u16 >> key_share: length_data!(be_u16) >> record_digest: length_data!(be_u16) >> encrypted_sni: length_data!(be_u16) >> ( TlsExtension::EncryptedServerName{ ciphersuite:TlsCipherSuiteID(ciphersuite), group: NamedGroup(group), key_share, record_digest, encrypted_sni} ) } } named! {parse_tls_oid_filter, do_parse!( oid: length_data!(be_u8) >> val: length_data!(be_u16) >> ( OidFilter{cert_ext_oid:oid, cert_ext_val:val} ) ) } /// Defined in TLS 1.3 draft 19 fn parse_tls_extension_oid_filters(i: &[u8]) -> IResult<&[u8], TlsExtension> { do_parse! { i, l: be_u16 >> v: flat_map!(take!(l),many0!(complete!(parse_tls_oid_filter))) >> ( 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> { do_parse! { i, error_if!(ext_len != 0, ErrorKind::Verify) >> ( TlsExtension::PostHandshakeAuth ) } } named! {pub parse_tls_extension_unknown, do_parse!( ext_type: be_u16 >> ext_len: be_u16 >> ext_data: take!(ext_len) >> ( TlsExtension::Unknown(TlsExtensionType(ext_type),ext_data) ) ) } fn parse_tls_extension_with_type( i: &[u8], ext_type: u16, ext_len: u16, ) -> IResult<&[u8], TlsExtension> { if ext_type & 0x0f0f == 0x0a0a { return map!(i, take!(ext_len), |d| TlsExtension::Grease(ext_type, d)); } match ext_type { 0x0000 => parse_tls_extension_sni_content(i), 0x0001 => parse_tls_extension_max_fragment_length_content(i), 0x0005 => parse_tls_extension_status_request_content(i, ext_len), 0x000a => parse_tls_extension_elliptic_curves_content(i), 0x000b => parse_tls_extension_ec_point_formats_content(i), 0x000d => parse_tls_extension_signature_algorithms_content(i), 0x000f => parse_tls_extension_heartbeat_content(i), 0x0010 => parse_tls_extension_alpn_content(i), 0x0012 => parse_tls_extension_signed_certificate_timestamp_content(i), 0x0015 => parse_tls_extension_padding_content(i, ext_len), 0x0016 => parse_tls_extension_encrypt_then_mac_content(i, ext_len), 0x0017 => parse_tls_extension_extended_master_secret_content(i, ext_len), 0x001c => parse_tls_extension_record_size_limit(i), 0x0023 => parse_tls_extension_session_ticket_content(i, ext_len), 0x0028 => parse_tls_extension_key_share_old_content(i, ext_len), 0x0029 => parse_tls_extension_pre_shared_key_content(i, ext_len), 0x002a => parse_tls_extension_early_data_content(i, ext_len), 0x002b => parse_tls_extension_supported_versions_content(i, ext_len), 0x002c => parse_tls_extension_cookie_content(i, ext_len), 0x002d => parse_tls_extension_psk_key_exchange_modes_content(i), 0x0030 => parse_tls_extension_oid_filters(i), 0x0031 => parse_tls_extension_post_handshake_auth_content(i, ext_len), 0x0033 => parse_tls_extension_key_share_content(i, ext_len), 0x3374 => parse_tls_extension_npn_content(i, ext_len), 0xff01 => parse_tls_extension_renegotiation_info_content(i), 0xffce => parse_tls_extension_encrypted_server_name(i), _ => map!(i, take!(ext_len), |ext_data| { TlsExtension::Unknown(TlsExtensionType(ext_type), ext_data) }), } } named! {pub parse_tls_extension, do_parse!( ext_type: be_u16 >> ext_len: be_u16 >> ext: flat_map!(take!(ext_len),call!(parse_tls_extension_with_type,ext_type,ext_len)) >> ( ext ) ) } named!(pub parse_tls_extensions >, many0!(complete!(parse_tls_extension)) ); tls-parser-0.9.2/src/tls_serialize.rs010064400017500001750000000461271355332076100160640ustar0000000000000000#[cfg(feature = "serialize")] pub mod serialize { use crate::tls::*; use crate::tls_ec::{ECPoint, NamedGroup}; use crate::tls_extensions::{SNIType, TlsExtension, TlsExtensionType}; use cookie_factory::gen::{set_be_u16, set_be_u8}; use cookie_factory::*; #[macro_export] macro_rules! gen_tagged_extension( (($i:expr, $idx:expr), $tag:expr, $submac:ident!( $($args:tt)* )) => ( do_gen!(($i,$idx), gen_be_u16!($tag) >> ofs: gen_skip!(2) >> start: $submac!( $($args)* ) >> end: gen_at_offset!(ofs,gen_be_u16!((end-start) as u16)) ) ); (($i:expr, $idx:expr), $tag:expr, $f:ident( $($args:tt)* )) => ( gen_tagged_extension!(($i,$idx), $tag, $gen_call!($f( $($args)* ))) ); ($x:expr, $tag:expr, $submac:ident!( $($args:tt)* )) => ( gen_tagged_extension!(($x.0, $x.1), $tag, $submac!( $($args)* )) ); ($x:expr, $tag:expr, $f:ident( $($args:tt)* )) => ( gen_tagged_extension!(($x.0, $x.1), $tag, $f( $($args)* )) ); ); #[macro_export] macro_rules! gen_length_bytes_be_u16( (($i:expr, $idx:expr), $submac:ident!( $($args:tt)* )) => ( do_gen!(($i,$idx), ofs: gen_skip!(2) >> start: $submac!( $($args)* ) >> end: gen_at_offset!(ofs,gen_be_u16!((end-start) as u16)) ) ); (($i:expr, $idx:expr), $f:ident( $($args:tt)* )) => ( gen_length_bytes_be_u16!(($i,$idx), $gen_call!($f( $($args)* ))) ); ($x:ident, $submac:ident!( $($args:tt)* )) => ( gen_length_bytes_be_u16!(($x.0,$x.1), $submac!( $($args)* ))); ($x:ident, $f:ident( $($args:tt)* )) => ( gen_length_bytes_be_u16!(($x.0,$x.1), $f( $($args)* ))); ); #[macro_export] macro_rules! gen_many_deref( (($i:expr, $idx:expr), $l:expr, $f:expr) => ( $l.into_iter().fold( Ok(($i,$idx)), |r,&v| { match r { Err(e) => Err(e), Ok(x) => { $f(x, (*v)) }, } } ) ); ); #[inline] pub fn gen_tls_named_group<'a>( x: (&'a mut [u8], usize), g: NamedGroup, ) -> Result<(&'a mut [u8], usize), GenError> { set_be_u16(x, g.0) } #[inline] pub fn gen_tls_ec_point<'a>( x: (&'a mut [u8], usize), p: ECPoint, ) -> Result<(&'a mut [u8], usize), GenError> { do_gen! { x, gen_be_u8!(p.point.len() as u8) >> gen_slice!(p.point) } } pub fn gen_tls_ext_sni_hostname<'a, 'b>( x: (&'a mut [u8], usize), h: &(SNIType, &'b [u8]), ) -> Result<(&'a mut [u8], usize), GenError> { do_gen! { x, gen_be_u8!((h.0).0 as u8) >> gen_be_u16!(h.1.len() as u16) >> gen_slice!(h.1) } } #[inline] pub fn gen_tls_ext_sni<'a, 'b>( x: (&'a mut [u8], usize), m: &'b Vec<(SNIType, &'b [u8])>, ) -> Result<(&'a mut [u8], usize), GenError> { gen_tagged_extension!(x, 0x0000, gen_many_ref!(m, gen_tls_ext_sni_hostname)) } #[inline] pub fn gen_tls_ext_max_fragment_length<'a, 'b>( x: (&'a mut [u8], usize), l: u8, ) -> Result<(&'a mut [u8], usize), GenError> { gen_tagged_extension!(x, 0x0001, gen_be_u8!(l)) } #[inline] pub fn gen_tls_ext_elliptic_curves<'a, 'b>( x: (&'a mut [u8], usize), v: &'b Vec, ) -> Result<(&'a mut [u8], usize), GenError> { gen_tagged_extension!( x, u16::from(TlsExtensionType::SupportedGroups), gen_length_bytes_be_u16!(gen_many_byref!(v, gen_tls_named_group)) ) } pub fn gen_tls_extension<'a, 'b>( x: (&'a mut [u8], usize), m: &'b TlsExtension, ) -> Result<(&'a mut [u8], usize), GenError> { match m { &TlsExtension::SNI(ref v) => gen_tls_ext_sni(x, v), &TlsExtension::MaxFragmentLength(l) => gen_tls_ext_max_fragment_length(x, l), &TlsExtension::EllipticCurves(ref v) => gen_tls_ext_elliptic_curves(x, v), _ => Err(GenError::NotYetImplemented), } } pub fn gen_tls_extensions<'a, 'b>( x: (&'a mut [u8], usize), m: &'b Vec, ) -> Result<(&'a mut [u8], usize), GenError> { gen_length_bytes_be_u16!(x, gen_many_ref!(m, gen_tls_extension)) } #[inline] pub fn gen_tls_sessionid<'a, 'b>( x: (&'a mut [u8], usize), m: &Option<&'b [u8]>, ) -> Result<(&'a mut [u8], usize), GenError> { match m { &None => gen_be_u8!(x, 0), &Some(o) => { do_gen! { x, gen_be_u8!(o.len() as u8) >> gen_slice!(o) } } } } pub fn gen_tls_hellorequest<'a>( x: (&'a mut [u8], usize), ) -> Result<(&'a mut [u8], usize), GenError> { do_gen! { x, gen_be_u8!(u8::from(TlsHandshakeType::HelloRequest)) >> gen_be_u24!(0) } } pub fn gen_tls_clienthello<'a, 'b>( x: (&'a mut [u8], usize), m: &'b TlsClientHelloContents, ) -> Result<(&'a mut [u8], usize), GenError> { do_gen! { x, gen_be_u8!(u8::from(TlsHandshakeType::ClientHello)) >> ofs_len: gen_skip!(3) >> start: gen_be_u16!(u16::from(m.version)) >> gen_be_u32!(m.rand_time) >> gen_copy!(m.rand_data,28) >> gen_tls_sessionid(&m.session_id) >> gen_be_u16!((m.ciphers.len()*2) as u16) >> gen_many_deref!(&m.ciphers,set_be_u16) >> gen_be_u8!(m.comp.len() as u8) >> gen_many_deref!(&m.comp,set_be_u8) >> gen_cond!(m.ext.is_some(),gen_slice!(m.ext.unwrap())) >> end: gen_at_offset!(ofs_len,gen_be_u24!((end-start) as u32)) } } pub fn gen_tls_serverhello<'a, 'b>( x: (&'a mut [u8], usize), m: &'b TlsServerHelloContents, ) -> Result<(&'a mut [u8], usize), GenError> { do_gen! { x, gen_be_u8!(u8::from(TlsHandshakeType::ServerHello)) >> ofs_len: gen_skip!(3) >> start: gen_be_u16!(u16::from(m.version)) >> gen_be_u32!(m.rand_time) >> gen_copy!(m.rand_data,28) >> gen_tls_sessionid(&m.session_id) >> gen_be_u16!(*m.cipher) >> gen_be_u8!(*m.compression) >> gen_cond!(m.ext.is_some(),gen_slice!(m.ext.unwrap())) >> end: gen_at_offset!(ofs_len,gen_be_u24!((end-start) as u32)) } } pub fn gen_tls_serverhellov13draft18<'a, 'b>( x: (&'a mut [u8], usize), m: &'b TlsServerHelloV13Draft18Contents, ) -> Result<(&'a mut [u8], usize), GenError> { do_gen! { x, gen_be_u8!(u8::from(TlsHandshakeType::ServerHello)) >> ofs_len: gen_skip!(3) >> start: gen_copy!(m.random,32) >> gen_be_u16!(*m.cipher) >> gen_cond!(m.ext.is_some(),gen_slice!(m.ext.unwrap())) >> end: gen_at_offset!(ofs_len,gen_be_u24!((end-start) as u32)) } } pub fn gen_tls_finished<'a, 'b>( x: (&'a mut [u8], usize), m: &'b [u8], ) -> Result<(&'a mut [u8], usize), GenError> { do_gen! { x, gen_be_u8!(u8::from(TlsHandshakeType::ServerHello)) >> ofs_len: gen_skip!(3) >> start: gen_slice!(m) >> end: gen_at_offset!(ofs_len,gen_be_u24!((end-start) as u32)) } } pub fn gen_tls_clientkeyexchange_unknown<'a, 'b>( x: (&'a mut [u8], usize), m: &'b [u8], ) -> Result<(&'a mut [u8], usize), GenError> { do_gen! { x, gen_be_u8!(u8::from(TlsHandshakeType::ClientKeyExchange)) >> gen_be_u24!(m.len() as u32) >> gen_slice!(m) } } pub fn gen_tls_clientkeyexchange_dh<'a, 'b>( x: (&'a mut [u8], usize), m: &'b [u8], ) -> Result<(&'a mut [u8], usize), GenError> { // for DH, length is 2 bytes do_gen! { x, gen_be_u8!(u8::from(TlsHandshakeType::ClientKeyExchange)) >> ofs_len: gen_skip!(3) >> start: gen_be_u16!(m.len() as u16) >> gen_slice!(m) >> end: gen_at_offset!(ofs_len,gen_be_u24!((end-start) as u32)) } } pub fn gen_tls_clientkeyexchange_ecdh<'a, 'b>( x: (&'a mut [u8], usize), m: &'b ECPoint, ) -> Result<(&'a mut [u8], usize), GenError> { // for ECDH, length is only 1 byte do_gen! { x, gen_be_u8!(u8::from(TlsHandshakeType::ClientKeyExchange)) >> ofs_len: gen_skip!(3) >> start: gen_skip!(1) >> s2: gen_slice!(m.point) >> end: gen_at_offset!(start,gen_be_u8!((end-s2) as u8)) >> gen_at_offset!(ofs_len,gen_be_u24!((end-start) as u32)) } } pub fn gen_tls_clientkeyexchange<'a, 'b>( x: (&'a mut [u8], usize), m: &'b TlsClientKeyExchangeContents, ) -> Result<(&'a mut [u8], usize), GenError> { match m { &TlsClientKeyExchangeContents::Unknown(ref b) => { gen_tls_clientkeyexchange_unknown(x, b) } &TlsClientKeyExchangeContents::Dh(ref b) => gen_tls_clientkeyexchange_dh(x, b), &TlsClientKeyExchangeContents::Ecdh(ref b) => gen_tls_clientkeyexchange_ecdh(x, b), } } pub fn gen_tls_messagehandshake<'a, 'b>( x: (&'a mut [u8], usize), m: &'b TlsMessageHandshake, ) -> Result<(&'a mut [u8], usize), GenError> { match m { &TlsMessageHandshake::HelloRequest => gen_tls_hellorequest(x), &TlsMessageHandshake::ClientHello(ref m) => gen_tls_clienthello(x, m), &TlsMessageHandshake::ServerHello(ref m) => gen_tls_serverhello(x, m), &TlsMessageHandshake::ServerHelloV13Draft18(ref m) => { gen_tls_serverhellov13draft18(x, m) } &TlsMessageHandshake::ClientKeyExchange(ref m) => gen_tls_clientkeyexchange(x, m), &TlsMessageHandshake::Finished(ref m) => gen_tls_finished(x, m), _ => Err(GenError::NotYetImplemented), } } #[inline] pub fn gen_tls_changecipherspec<'a>( x: (&'a mut [u8], usize), ) -> Result<(&'a mut [u8], usize), GenError> { gen_be_u8!(x, 1) } pub fn gen_tls_message<'a, 'b>( x: (&'a mut [u8], usize), m: &'b TlsMessage, ) -> Result<(&'a mut [u8], usize), GenError> { match m { &TlsMessage::Handshake(ref m) => gen_tls_messagehandshake(x, m), &TlsMessage::ChangeCipherSpec => gen_tls_changecipherspec(x), _ => Err(GenError::NotYetImplemented), } } /// Write a TlsPlaintext record to the input slice /// /// if p.hdr.len is 0, compute the real size of the record /// otherwise, use the provided length pub fn gen_tls_plaintext<'a, 'b>( x: (&'a mut [u8], usize), p: &'b TlsPlaintext, ) -> Result<(&'a mut [u8], usize), GenError> { do_gen! { x, gen_be_u8!(u8::from(p.hdr.record_type)) >> gen_be_u16!(p.hdr.version.0) >> ofs_len: gen_be_u16!(p.hdr.len) >> // gen_skip!(2) >> start: gen_many_ref!(&p.msg,gen_tls_message) >> end: gen_cond!(p.hdr.len == 0, gen_at_offset!(ofs_len,gen_be_u16!((end-start) as u16))) } } #[cfg(test)] mod tests { use super::*; #[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: 213, }, msg: vec![TlsMessage::Handshake(TlsMessageHandshake::ClientHello( TlsClientHelloContents { version: TlsVersion::Tls12, rand_time: 0xb29dd787, rand_data: &rand_data, session_id: None, ciphers: ciphers.iter().map(|&x| TlsCipherSuiteID(x)).collect(), comp: comp, ext: None, }, ))], }; { let mut mem: [u8; 218] = [0; 218]; let s = &mut mem[..]; let res = gen_tls_plaintext((s, 0), &expected); match res { Ok((b, _)) => { let res_reparse = parse_tls_plaintext(b); assert_eq!(res_reparse, Ok((&b""[..], expected))); } Err(e) => println!("Error: {:?}", e), }; } } #[test] fn serialize_hellorequest() { let mut mem: [u8; 256] = [0; 256]; let s = &mut mem[..]; let m = TlsMessageHandshake::HelloRequest; let res = gen_tls_messagehandshake((s, 0), &m); match res { Ok((b, _)) => { let v = [0, 0, 0, 0]; assert_eq!(&b[..v.len()], v); } Err(e) => println!("Error: {:?}", e), }; } #[test] fn serialize_tls_ext() { let mut mem: [u8; 256] = [0; 256]; let s = &mut mem[..]; let ext = vec![TlsExtension::SNI(vec![( SNIType::HostName, b"www.google.com", )])]; let res = gen_many_ref!((s, 0), ext, gen_tls_extension); match res { Ok((b, idx)) => { let v = [ 0x00, 0x00, // SNI tag 0x00, 0x11, // SNI ext length // element 0: 0x00, // type 0x00, 0x0e, // length 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, ]; assert_eq!(idx, v.len()); assert_eq!(&b[..v.len()], &v[..]); } Err(e) => println!("Error: {:?}", e), }; } #[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: 0xb29dd787, rand_data: &rand_data, session_id: None, ciphers: ciphers.iter().map(|&x| TlsCipherSuiteID(x)).collect(), comp: comp, ext: None, }); let mut mem: [u8; 256] = [0; 256]; let s = &mut mem[..]; let res = gen_tls_messagehandshake((s, 0), &m); match res { Ok((b, idx)) => { let v = [ 0x01, 0x00, 0x00, 0x2b, 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 ]; assert_eq!(idx, v.len()); assert_eq!(&b[..v.len()], &v[..]); } Err(e) => println!("Error: {:?}", e), }; } #[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: 0xb29dd787, rand_data: &rand_data, session_id: None, cipher: TlsCipherSuiteID(0xc030), compression: TlsCompressionID(0), ext: None, }); let mut mem: [u8; 256] = [0; 256]; let s = &mut mem[..]; let res = gen_tls_messagehandshake((s, 0), &m); match res { Ok((b, idx)) => { let v = [ 0x02, 0x00, 0x00, 0x26, 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 ]; assert_eq!(idx, v.len()); assert_eq!(&b[..v.len()], &v[..]); } Err(e) => println!("Error: {:?}", e), }; } } } tls-parser-0.9.2/src/tls_sign_hash.rs010064400017500001750000000065451352002631700160320ustar0000000000000000use nom::number::streaming::{be_u16, be_u8}; use nom::IResult; /// Hash algorithms, as defined in [RFC5246] #[derive(Debug, PartialEq, Eq)] 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(Debug, PartialEq, Eq)] 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(PartialEq)] pub struct SignatureAndHashAlgorithm { pub hash: HashAlgorithm, pub sign: SignAlgorithm, } /// Signature algorithms, as defined in [RFC8446] 4.2.3 #[derive(Debug, PartialEq, Eq)] 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, /* 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, /* 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(PartialEq)] pub struct DigitallySigned<'a> { pub alg: Option, // pub alg: Option, // SignatureScheme pub data: &'a [u8], } named! {pub parse_digitally_signed_old, map!( length_data!(be_u16), |d| { DigitallySigned{ alg:None, data:d } } ) } named! {pub parse_digitally_signed, do_parse!( h: be_u8 >> s: be_u8 >> d: length_data!(be_u16) >> ( DigitallySigned{ alg: Some( SignatureAndHashAlgorithm{ hash:HashAlgorithm(h), sign:SignAlgorithm(s) } ), data: d, }) ) } /// 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!(i, fun, parse_digitally_signed) } else { pair!(i, fun, parse_digitally_signed_old) } } tls-parser-0.9.2/src/tls_states.rs010064400017500001750000000154551352002643200153700ustar0000000000000000use 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 { 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(_), false) => 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 { 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), } } tls-parser-0.9.2/tests/tls_dh.rs010064400017500001750000000246431355234366100150450ustar0000000000000000#[macro_use] extern crate nom; extern crate tls_parser; mod tls_dh { use tls_parser::*; #[rustfmt::skip] static ECDHE_PARAMS: &'static [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!(bytes, parse_ecdh_params, parse_digitally_signed); assert_eq!(res, Ok((empty, (expected1, expected2)))); } #[rustfmt::skip] static DHE_PARAMS: &'static [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!(bytes, parse_dh_params, parse_digitally_signed); assert_eq!(res, Ok((empty, (expected1, expected2)))); } } // mod tls_dh tls-parser-0.9.2/tests/tls_extensions.rs010064400017500001750000000152321355234366100166430ustar0000000000000000#[macro_use] extern crate pretty_assertions; extern crate nom; extern crate tls_parser; mod tls_extensions { use tls_parser::*; #[rustfmt::skip] static CLIENT_EXTENSIONS1: &'static [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 tls-parser-0.9.2/tests/tls_handshake.rs010064400017500001750000001356461355234366100164060ustar0000000000000000#[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 : &'static [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: 0xb29dd787, rand_data: &rand_data, session_id: None, ciphers: ciphers.iter().map(|&x| TlsCipherSuiteID(x)).collect(), comp: 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: &'static [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: 0x57c457da, 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: &'static [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: &'static [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::Size(255))); 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: &'static [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: &'static [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: &'static [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: 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 tls-parser-0.9.2/tests/tls_tls13.rs010064400017500001750000000151041355234366100154100ustar0000000000000000extern 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: &'static [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: &'static [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: 0xce05cfa3, 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() } _ => { assert!(false); empty } }; let res_ext = parse_tls_extensions(ext_raw); assert_eq!(res_ext, Ok((empty, expected_ext))); } } // mod tls_13 tls-parser-0.9.2/.cargo_vcs_info.json0000644000000001120000000000000131710ustar00{ "git": { "sha1": "82cf6712fc653ce558ff2a1665eddabf3cfa3499" } }