Skip to content

Commit

Permalink
tls_record: Add client_hello and tls_extension implement
Browse files Browse the repository at this point in the history
tls_extension currently only supports the supported_versions
extension.
  • Loading branch information
windowsair authored and laudrup committed Oct 16, 2024
1 parent 9613e5c commit 32e1f57
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 3 deletions.
80 changes: 78 additions & 2 deletions test/tls_record.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<const char*>(buffer.data()), length);
buffer += length;
return ret;
}

std::uint32_t read_three_byte_value(net::const_buffer& buffer) {
assert(buffer.size() >= 3);
std::array<char, 4> value{};
Expand All @@ -51,12 +58,12 @@ tls_record::message_type read_message(tls_record::record_type type, net::const_b
WINTLS_UNREACHABLE_RETURN(0);
}

tls_handshake::message_type read_message(tls_handshake::handshake_type t, net::const_buffer&) {
tls_handshake::message_type read_message(tls_handshake::handshake_type t, net::const_buffer& buffer) {
switch(t) {
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:
Expand All @@ -77,8 +84,57 @@ 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::supported_versions:
return tls_extension::supported_versions{buffer};
case tls_extension::extension_type::server_name:
case tls_extension::extension_type::max_fragment_length:
case tls_extension::extension_type::status_request:
case tls_extension::extension_type::supported_group:
case tls_extension::extension_type::signature_algorithms:
case tls_extension::extension_type::use_srtp:
case tls_extension::extension_type::heartbeat:
case tls_extension::extension_type::application_layer_protocol_negotiation:
case tls_extension::extension_type::signed_certificate_timestamp:
case tls_extension::extension_type::client_certificate_type:
case tls_extension::extension_type::server_certificate_type:
case tls_extension::extension_type::padding:
case tls_extension::extension_type::pre_shared_key:
case tls_extension::extension_type::early_data:
case tls_extension::extension_type::cookie:
case tls_extension::extension_type::psk_key_exchange_modes:
case tls_extension::extension_type::certificate_authorities:
case tls_extension::extension_type::oid_filters:
case tls_extension::extension_type::post_handshake_auth:
case tls_extension::extension_type::signature_algorithms_cert:
case tls_extension::extension_type::key_share:
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<tls_version>(read_value<std::uint16_t>(data));
random = read_buffer(data, 32);
session_id_length = read_value<std::uint8_t>(data);
session_id = read_buffer(data, session_id_length);
cipher_suites_length = read_value<std::uint16_t>(data);
cipher_suites = read_buffer(data, cipher_suites_length);
compression_methods_length = read_value<std::uint8_t>(data);
compression_methods = read_buffer(data, compression_methods_length);
extensions_length = read_value<std::uint16_t>(data);

while (data.size()) {
extension.emplace_back(data);
}
}

tls_handshake::tls_handshake(net::const_buffer data)
: type(static_cast<handshake_type>(read_value<std::uint8_t>(data)))
, size(read_three_byte_value(data))
Expand All @@ -91,3 +147,23 @@ tls_record::tls_record(net::const_buffer data)
, size(read_value<std::uint16_t>(data))
, message(read_message(type, data)) {
}

tls_extension::tls_extension(net::const_buffer& data)
: type(static_cast<extension_type>(read_value<std::uint16_t>(data)))
, size(read_value<std::uint16_t>(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<std::uint8_t>(data);

version_length /= 2; // 2byte per version field

for (int i = 0; i < version_length; i++) {
version.emplace_back(static_cast<tls_version>(read_value<std::uint16_t>(data)));
}
}
61 changes: 60 additions & 1 deletion test/tls_record.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<tls_version> version;
};

struct common {
common(net::const_buffer& data, std::uint16_t size);

net::const_buffer message;
};

using message_type = variant::variant<supported_versions, common>;

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,
Expand All @@ -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<tls_extension> extension;

client_hello(net::const_buffer& data);
};

struct server_hello {
Expand Down

0 comments on commit 32e1f57

Please sign in to comment.