Botan 3.5.0
Crypto and TLS for C&
tls_handshake_layer_13.cpp
Go to the documentation of this file.
1/*
2* TLS handshake state (machine) implementation for TLS 1.3
3* (C) 2022 Jack Lloyd
4* 2022 Hannes Rantzsch, René Meusel - neXenio GmbH
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#include <botan/internal/tls_handshake_layer_13.h>
10
11#include <botan/tls_alert.h>
12#include <botan/tls_exceptn.h>
13#include <botan/internal/stl_util.h>
14#include <botan/internal/tls_reader.h>
15#include <botan/internal/tls_transcript_hash_13.h>
16
17namespace Botan::TLS {
18
19void Handshake_Layer::copy_data(std::span<const uint8_t> data_from_peer) {
20 m_read_buffer.insert(m_read_buffer.end(), data_from_peer.begin(), data_from_peer.end());
21}
22
23namespace {
24
25constexpr size_t HEADER_LENGTH = 4;
26
27template <typename Msg_Type>
28Handshake_Type handshake_type_from_byte(uint8_t byte_value) {
29 const auto type = static_cast<Handshake_Type>(byte_value);
30
31 if constexpr(std::is_same_v<Msg_Type, Handshake_Message_13>) {
32 switch(type) {
35 // case Handshake_Type::EndOfEarlyData: // NYI: needs PSK/resumption support -- won't be offered in Client Hello for now
41 return type;
42 default:
43 throw TLS_Exception(AlertType::UnexpectedMessage, "Unknown handshake message received");
44 }
45 } else {
46 switch(type) {
49 // case Handshake_Type::CertificateRequest: // NYI: post-handshake client auth (RFC 8446 4.6.2) -- won't be offered in Client Hello for now
50 return type;
51 default:
52 throw TLS_Exception(AlertType::UnexpectedMessage, "Unknown post-handshake message received");
53 }
54 }
55}
56
57template <typename Msg_Type>
58std::optional<Msg_Type> parse_message(TLS::TLS_Data_Reader& reader,
59 const Policy& policy,
60 const Connection_Side peer_side,
61 const Certificate_Type cert_type) {
62 // read the message header
63 if(reader.remaining_bytes() < HEADER_LENGTH) {
64 return std::nullopt;
65 }
66
67 Handshake_Type type = handshake_type_from_byte<Msg_Type>(reader.get_byte());
68
69 // make sure we have received the full message
70 const size_t msg_len = reader.get_uint24_t();
71 if(reader.remaining_bytes() < msg_len) {
72 return std::nullopt;
73 }
74
75 // create the message
76 const auto msg = reader.get_fixed<uint8_t>(msg_len);
77 if constexpr(std::is_same_v<Msg_Type, Handshake_Message_13>) {
78 switch(type) {
79 // Client Hello and Server Hello messages are ambiguous. Both may come
80 // from non-TLS 1.3 peers. Hence, their parsing is somewhat different.
82 // ... might be TLS 1.2 Client Hello or TLS 1.3 Client Hello
85 // ... might be TLS 1.2 Server Hello or TLS 1.3 Server Hello or
86 // a TLS 1.3 Hello Retry Request disguising as a Server Hello
88 // case Handshake_Type::EndOfEarlyData:
89 // return End_Of_Early_Data(msg);
91 return Encrypted_Extensions(msg);
93 return Certificate_13(msg, policy, peer_side, cert_type);
95 return Certificate_Request_13(msg, peer_side);
97 return Certificate_Verify_13(msg, peer_side);
99 return Finished_13(msg);
100 default:
101 BOTAN_ASSERT(false, "cannot be reached"); // make sure to update handshake_type_from_byte
102 }
103 } else {
104 BOTAN_UNUSED(peer_side);
105
106 switch(type) {
108 return New_Session_Ticket_13(msg, peer_side);
110 return Key_Update(msg);
111 default:
112 BOTAN_ASSERT(false, "cannot be reached"); // make sure to update handshake_type_from_byte
113 }
114 }
115}
116
117} // namespace
118
119std::optional<Handshake_Message_13> Handshake_Layer::next_message(const Policy& policy,
120 Transcript_Hash_State& transcript_hash) {
121 TLS::TLS_Data_Reader reader("handshake message", m_read_buffer);
122
123 auto msg = parse_message<Handshake_Message_13>(reader, policy, m_peer, m_certificate_type);
124 if(msg.has_value()) {
125 BOTAN_ASSERT_NOMSG(m_read_buffer.size() >= reader.read_so_far());
126 transcript_hash.update(std::span{m_read_buffer.data(), reader.read_so_far()});
127 m_read_buffer.erase(m_read_buffer.cbegin(), m_read_buffer.cbegin() + reader.read_so_far());
128 }
129
130 return msg;
131}
132
133std::optional<Post_Handshake_Message_13> Handshake_Layer::next_post_handshake_message(const Policy& policy) {
134 TLS::TLS_Data_Reader reader("post handshake message", m_read_buffer);
135
136 auto msg = parse_message<Post_Handshake_Message_13>(reader, policy, m_peer, m_certificate_type);
137 if(msg.has_value()) {
138 m_read_buffer.erase(m_read_buffer.cbegin(), m_read_buffer.cbegin() + reader.read_so_far());
139 }
140
141 return msg;
142}
143
144namespace {
145
146template <typename T>
147const T& get(const std::reference_wrapper<T>& v) {
148 return v.get();
149}
150
151template <typename T>
152const T& get(const T& v) {
153 return v;
154}
155
156template <typename T>
157std::vector<uint8_t> marshall_message(const T& message) {
158 auto [type, serialized] =
159 std::visit([](const auto& msg) { return std::pair(get(msg).wire_type(), get(msg).serialize()); }, message);
160
161 BOTAN_ASSERT_NOMSG(serialized.size() <= 0xFFFFFF);
162 const uint32_t msg_size = static_cast<uint32_t>(serialized.size());
163
164 std::vector<uint8_t> header{
165 static_cast<uint8_t>(type), get_byte<1>(msg_size), get_byte<2>(msg_size), get_byte<3>(msg_size)};
166
167 return concat(header, serialized);
168}
169
170} //namespace
171
173 Transcript_Hash_State& transcript_hash) {
174 auto msg = marshall_message(message);
175 transcript_hash.update(msg);
176 return msg;
177}
178
180 return marshall_message(message);
181}
182
183} // namespace Botan::TLS
#define BOTAN_UNUSED
Definition assert.h:118
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:50
static std::variant< Client_Hello_13, Client_Hello_12 > parse(const std::vector< uint8_t > &buf)
static std::vector< uint8_t > prepare_message(Handshake_Message_13_Ref message, Transcript_Hash_State &transcript_hash)
std::optional< Handshake_Message_13 > next_message(const Policy &policy, Transcript_Hash_State &transcript_hash)
std::optional< Post_Handshake_Message_13 > next_post_handshake_message(const Policy &policy)
static std::vector< uint8_t > prepare_post_handshake_message(const Post_Handshake_Message_13 &message)
void copy_data(std::span< const uint8_t > data_from_peer)
static std::variant< Hello_Retry_Request, Server_Hello_13, Server_Hello_12 > parse(const std::vector< uint8_t > &buf)
size_t read_so_far() const
Definition tls_reader.h:35
void update(std::span< const uint8_t > serialized_message_s)
FE_25519 T
Definition ge.cpp:34
as_wrapped_references_t< Handshake_Message_13 > Handshake_Message_13_Ref
std::variant< New_Session_Ticket_13, Key_Update > Post_Handshake_Message_13
constexpr GeneralVariantT generalize_to(SpecialT &&specific) noexcept
Converts a given variant into another variant-ish whose type states are a super set of the given vari...
Definition stl_util.h:314
constexpr uint8_t get_byte(T input)
Definition loadstor.h:75
constexpr auto concat(Rs &&... ranges)
Definition stl_util.h:262