From 3ebce4fa4e65b419755495c81a40ee2a24fabbb5 Mon Sep 17 00:00:00 2001 From: windowsair Date: Mon, 22 Jul 2024 22:03:02 +0800 Subject: [PATCH] tls_record: Add client_hello and tls_extension implement tls_extension currently only supports the supported_versions extension. --- test/tls_record.cpp | 99 ++++++++++++++++++++++++++++++++++++++++++++- test/tls_record.hpp | 61 +++++++++++++++++++++++++++- 2 files changed, 158 insertions(+), 2 deletions(-) diff --git a/test/tls_record.cpp b/test/tls_record.cpp index 203bea94..a6c54436 100644 --- a/test/tls_record.cpp +++ b/test/tls_record.cpp @@ -29,6 +29,13 @@ SizeType read_value(net::const_buffer& buffer) { return net_to_host(ret); } +net::const_buffer read_buffer(net::const_buffer& buffer, std::size_t length) { + assert(buffer.size() >= length); + net::const_buffer ret(reinterpret_cast(buffer.data()), length); + buffer += length; + return ret; +} + std::uint32_t read_three_byte_value(net::const_buffer& buffer) { assert(buffer.size() >= 3); std::array value{}; @@ -56,7 +63,7 @@ tls_handshake::message_type read_message(tls_handshake::handshake_type t, net::c case tls_handshake::handshake_type::hello_request: return tls_handshake::hello_request{}; case tls_handshake::handshake_type::client_hello: - return tls_handshake::client_hello{}; + return tls_handshake::client_hello{buffer}; case tls_handshake::handshake_type::server_hello: return tls_handshake::server_hello{}; case tls_handshake::handshake_type::certificate: @@ -77,8 +84,78 @@ tls_handshake::message_type read_message(tls_handshake::handshake_type t, net::c WINTLS_UNREACHABLE_RETURN(0); } +tls_extension::message_type read_message(tls_extension::extension_type t, + net::const_buffer& buffer, + std::uint16_t size) { + switch (t) { + case tls_extension::extension_type::server_name: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::max_fragment_length: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::status_request: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::supported_group: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::signature_algorithms: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::use_srtp: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::heartbeat: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::application_layer_protocol_negotiation: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::signed_certificate_timestamp: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::client_certificate_type: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::server_certificate_type: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::padding: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::pre_shared_key: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::early_data: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::supported_versions: + return tls_extension::supported_versions{buffer}; + case tls_extension::extension_type::cookie: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::psk_key_exchange_modes: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::certificate_authorities: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::oid_filters: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::post_handshake_auth: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::signature_algorithms_cert: + return tls_extension::common{buffer, size}; + case tls_extension::extension_type::key_share: + return tls_extension::common{buffer, size}; + default: + return tls_extension::common{buffer, size}; + } + WINTLS_UNREACHABLE_RETURN(0); +} + } // namespace +tls_handshake::client_hello::client_hello(net::const_buffer& data) { + version = static_cast(read_value(data)); + random = read_buffer(data, 32); + session_id_length = read_value(data); + session_id = read_buffer(data, session_id_length); + cipher_suites_length = read_value(data); + cipher_suites = read_buffer(data, cipher_suites_length); + compression_methods_length = read_value(data); + compression_methods = read_buffer(data, compression_methods_length); + extensions_length = read_value(data); + + while (data.size()) { + extension.emplace_back(data); + } +} + tls_handshake::tls_handshake(net::const_buffer data) : type(static_cast(read_value(data))) , size(read_three_byte_value(data)) @@ -91,3 +168,23 @@ tls_record::tls_record(net::const_buffer data) , size(read_value(data)) , message(read_message(type, data)) { } + +tls_extension::tls_extension(net::const_buffer& data) + : type(static_cast(read_value(data))) + , size(read_value(data)) + , message(read_message(type, data, size)) { +} + +tls_extension::common::common(net::const_buffer& data, std::uint16_t size) + : message(read_buffer(data, size)) { +} + +tls_extension::supported_versions::supported_versions(net::const_buffer& data) { + auto version_length = read_value(data); + + version_length /= 2; // 2byte per version field + + for (int i = 0; i < version_length; i++) { + version.emplace_back(static_cast(read_value(data))); + } +} diff --git a/test/tls_record.hpp b/test/tls_record.hpp index 6104d6f7..9c6b1db5 100644 --- a/test/tls_record.hpp +++ b/test/tls_record.hpp @@ -38,6 +38,54 @@ struct tls_alert { // TODO: Implement }; +struct tls_extension { + enum class extension_type : std::uint16_t { + server_name = 0, /* RFC 6066 */ + max_fragment_length = 1, /* RFC 6066 */ + status_request = 5, /* RFC 6066 */ + supported_group = 10, /* RFC 8422, 7919 */ + signature_algorithms = 13, /* RFC 8446 */ + use_srtp = 14, /* RFC 5764 */ + heartbeat = 15, /* RFC 6520 */ + application_layer_protocol_negotiation = 16, /* RFC 7301 */ + signed_certificate_timestamp = 18, /* RFC 6962 */ + client_certificate_type = 19, /* RFC 7250 */ + server_certificate_type = 20, /* RFC 7250 */ + padding = 21, /* RFC 7685 */ + pre_shared_key = 41, /* RFC 8446 */ + early_data = 42, /* RFC 8446 */ + supported_versions = 43, /* RFC 8446 */ + cookie = 44, /* RFC 8446 */ + psk_key_exchange_modes = 45, /* RFC 8446 */ + certificate_authorities = 47, /* RFC 8446 */ + oid_filters = 48, /* RFC 8446 */ + post_handshake_auth = 49, /* RFC 8446 */ + signature_algorithms_cert = 50, /* RFC 8446 */ + key_share = 51, /* RFC 8446 */ + max_extension_type = 65535 + }; + + struct supported_versions { + supported_versions(net::const_buffer& data); + + std::vector version; + }; + + struct common { + common(net::const_buffer& data, std::uint16_t size); + + net::const_buffer message; + }; + + using message_type = variant::variant; + + tls_extension(net::const_buffer& data); + + extension_type type; + std::uint16_t size; + message_type message; +}; + struct tls_handshake { enum class handshake_type : std::uint8_t { hello_request = 0x00, @@ -57,7 +105,18 @@ struct tls_handshake { }; struct client_hello { - // TODO: Implement + tls_version version; + net::const_buffer random; + std::uint8_t session_id_length; + net::const_buffer session_id; + std::uint16_t cipher_suites_length; + net::const_buffer cipher_suites; + std::uint8_t compression_methods_length; + net::const_buffer compression_methods; + std::uint16_t extensions_length; + std::vector extension; + + client_hello(net::const_buffer& data); }; struct server_hello {