Skip to content

Commit a8ca18f

Browse files
committed
Refactor: Disentangle Server_Hello implementations
This moves the implementation of Server_Hello_12 into the tls12 module and Server_Hello_13 to tls13 likewise. To support downgrading the protocol version, the TLS 1.3 implementation needs to have a rudimentary understanding of the TLS 1.2 Server Hello. This is now implemented by the Server_Hello_12_Shim base class.
1 parent 1d119e5 commit a8ca18f

15 files changed

Lines changed: 917 additions & 800 deletions

src/lib/tls/info.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ tls_version.h
4040
<header:internal>
4141
tls_channel_impl.h
4242
tls_handshake_transitions.h
43+
tls_messages_internal.h
4344
tls_reader.h
4445
</header:internal>
4546

src/lib/tls/msg_server_hello.cpp

Lines changed: 55 additions & 716 deletions
Large diffs are not rendered by default.
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
/*
2+
* TLS Server Hello and Server Hello Done
3+
* (C) 2004-2011,2015,2016,2019 Jack Lloyd
4+
* 2016 Matthias Gierlings
5+
* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity
6+
*
7+
* Botan is released under the Simplified BSD License (see license.txt)
8+
*/
9+
10+
#include <botan/tls_messages_12.h>
11+
12+
#include <botan/tls_callbacks.h>
13+
#include <botan/tls_extensions.h>
14+
#include <botan/tls_policy.h>
15+
#include <botan/internal/tls_handshake_hash.h>
16+
#include <botan/internal/tls_handshake_io.h>
17+
#include <botan/internal/tls_messages_internal.h>
18+
19+
namespace Botan::TLS {
20+
21+
// New session case
22+
Server_Hello_12::Server_Hello_12(Handshake_IO& io,
23+
Handshake_Hash& hash,
24+
const Policy& policy,
25+
Callbacks& cb,
26+
RandomNumberGenerator& rng,
27+
const std::vector<uint8_t>& reneg_info,
28+
const Client_Hello_12& client_hello,
29+
const Server_Hello_12::Settings& server_settings,
30+
std::string_view next_protocol) :
31+
Server_Hello_12(std::make_unique<Server_Hello_Internal>(
32+
server_settings.protocol_version(),
33+
server_settings.session_id(),
34+
make_server_hello_random(rng, server_settings.protocol_version(), cb, policy),
35+
server_settings.ciphersuite(),
36+
uint8_t(0))) {
37+
// NOLINTBEGIN(*-owning-memory)
38+
if(client_hello.supports_extended_master_secret()) {
39+
m_data->extensions().add(new Extended_Master_Secret);
40+
}
41+
42+
// Sending the extension back does not commit us to sending a stapled response
43+
if(client_hello.supports_cert_status_message() && policy.support_cert_status_message()) {
44+
m_data->extensions().add(new Certificate_Status_Request);
45+
}
46+
47+
if(!next_protocol.empty() && client_hello.supports_alpn()) {
48+
m_data->extensions().add(new Application_Layer_Protocol_Notification(next_protocol));
49+
}
50+
51+
const auto c = Ciphersuite::by_id(m_data->ciphersuite());
52+
53+
if(c && c->cbc_ciphersuite() && client_hello.supports_encrypt_then_mac() && policy.negotiate_encrypt_then_mac()) {
54+
m_data->extensions().add(new Encrypt_then_MAC);
55+
}
56+
57+
if(c && c->ecc_ciphersuite() && client_hello.extension_types().contains(Extension_Code::EcPointFormats)) {
58+
m_data->extensions().add(new Supported_Point_Formats(policy.use_ecc_point_compression()));
59+
}
60+
61+
if(client_hello.secure_renegotiation()) {
62+
m_data->extensions().add(new Renegotiation_Extension(reneg_info));
63+
}
64+
65+
if(client_hello.supports_session_ticket() && server_settings.offer_session_ticket()) {
66+
m_data->extensions().add(new Session_Ticket_Extension());
67+
}
68+
69+
if(m_data->legacy_version().is_datagram_protocol()) {
70+
const std::vector<uint16_t> server_srtp = policy.srtp_profiles();
71+
const std::vector<uint16_t> client_srtp = client_hello.srtp_profiles();
72+
73+
if(!server_srtp.empty() && !client_srtp.empty()) {
74+
uint16_t shared = 0;
75+
// always using server preferences for now
76+
for(auto s_srtp : server_srtp) {
77+
for(auto c_srtp : client_srtp) {
78+
if(shared == 0 && s_srtp == c_srtp) {
79+
shared = s_srtp;
80+
}
81+
}
82+
}
83+
84+
if(shared != 0) {
85+
m_data->extensions().add(new SRTP_Protection_Profiles(shared));
86+
}
87+
}
88+
}
89+
// NOLINTEND(*-owning-memory)
90+
91+
cb.tls_modify_extensions(m_data->extensions(), Connection_Side::Server, type());
92+
93+
hash.update(io.send(*this));
94+
}
95+
96+
// Resuming
97+
Server_Hello_12::Server_Hello_12(Handshake_IO& io,
98+
Handshake_Hash& hash,
99+
const Policy& policy,
100+
Callbacks& cb,
101+
RandomNumberGenerator& rng,
102+
const std::vector<uint8_t>& reneg_info,
103+
const Client_Hello_12& client_hello,
104+
const Session& resumed_session,
105+
bool offer_session_ticket,
106+
std::string_view next_protocol) :
107+
Server_Hello_12(std::make_unique<Server_Hello_Internal>(resumed_session.version(),
108+
client_hello.session_id(),
109+
make_hello_random(rng, cb, policy),
110+
resumed_session.ciphersuite_code(),
111+
uint8_t(0))) {
112+
// NOLINTBEGIN(*-owning-memory)
113+
if(client_hello.supports_extended_master_secret()) {
114+
m_data->extensions().add(new Extended_Master_Secret);
115+
}
116+
117+
if(!next_protocol.empty() && client_hello.supports_alpn()) {
118+
m_data->extensions().add(new Application_Layer_Protocol_Notification(next_protocol));
119+
}
120+
121+
if(client_hello.supports_encrypt_then_mac() && policy.negotiate_encrypt_then_mac()) {
122+
const Ciphersuite c = resumed_session.ciphersuite();
123+
if(c.cbc_ciphersuite()) {
124+
m_data->extensions().add(new Encrypt_then_MAC);
125+
}
126+
}
127+
128+
if(resumed_session.ciphersuite().ecc_ciphersuite() &&
129+
client_hello.extension_types().contains(Extension_Code::EcPointFormats)) {
130+
m_data->extensions().add(new Supported_Point_Formats(policy.use_ecc_point_compression()));
131+
}
132+
133+
if(client_hello.secure_renegotiation()) {
134+
m_data->extensions().add(new Renegotiation_Extension(reneg_info));
135+
}
136+
137+
if(client_hello.supports_session_ticket() && offer_session_ticket) {
138+
m_data->extensions().add(new Session_Ticket_Extension());
139+
}
140+
// NOLINTEND(*-owning-memory)
141+
142+
cb.tls_modify_extensions(m_data->extensions(), Connection_Side::Server, type());
143+
144+
hash.update(io.send(*this));
145+
}
146+
147+
Server_Hello_12::Server_Hello_12(const std::vector<uint8_t>& buf) :
148+
Server_Hello_12(std::make_unique<Server_Hello_Internal>(buf)) {}
149+
150+
Server_Hello_12::Server_Hello_12(std::unique_ptr<Server_Hello_Internal> data) : Server_Hello_12_Shim(std::move(data)) {}
151+
152+
bool Server_Hello_12::secure_renegotiation() const {
153+
return m_data->extensions().has<Renegotiation_Extension>();
154+
}
155+
156+
std::vector<uint8_t> Server_Hello_12::renegotiation_info() const {
157+
if(const Renegotiation_Extension* reneg = m_data->extensions().get<Renegotiation_Extension>()) {
158+
return reneg->renegotiation_info();
159+
}
160+
return std::vector<uint8_t>();
161+
}
162+
163+
bool Server_Hello_12::supports_extended_master_secret() const {
164+
return m_data->extensions().has<Extended_Master_Secret>();
165+
}
166+
167+
bool Server_Hello_12::supports_encrypt_then_mac() const {
168+
return m_data->extensions().has<Encrypt_then_MAC>();
169+
}
170+
171+
bool Server_Hello_12::supports_certificate_status_message() const {
172+
return m_data->extensions().has<Certificate_Status_Request>();
173+
}
174+
175+
bool Server_Hello_12::supports_session_ticket() const {
176+
return m_data->extensions().has<Session_Ticket_Extension>();
177+
}
178+
179+
uint16_t Server_Hello_12::srtp_profile() const {
180+
if(auto* srtp = m_data->extensions().get<SRTP_Protection_Profiles>()) {
181+
auto prof = srtp->profiles();
182+
if(prof.size() != 1 || prof[0] == 0) {
183+
throw Decoding_Error("Server sent malformed DTLS-SRTP extension");
184+
}
185+
return prof[0];
186+
}
187+
188+
return 0;
189+
}
190+
191+
std::string Server_Hello_12::next_protocol() const {
192+
if(auto* alpn = m_data->extensions().get<Application_Layer_Protocol_Notification>()) {
193+
return alpn->single_protocol();
194+
}
195+
return "";
196+
}
197+
198+
bool Server_Hello_12::prefers_compressed_ec_points() const {
199+
if(auto* ecc_formats = m_data->extensions().get<Supported_Point_Formats>()) {
200+
return ecc_formats->prefers_compressed();
201+
}
202+
return false;
203+
}
204+
205+
/*
206+
* Create a new Server Hello Done message
207+
*/
208+
Server_Hello_Done::Server_Hello_Done(Handshake_IO& io, Handshake_Hash& hash) {
209+
hash.update(io.send(*this));
210+
}
211+
212+
/*
213+
* Deserialize a Server Hello Done message
214+
*/
215+
Server_Hello_Done::Server_Hello_Done(const std::vector<uint8_t>& buf) {
216+
if(!buf.empty()) {
217+
throw Decoding_Error("Server_Hello_Done: Must be empty, and is not");
218+
}
219+
}
220+
221+
/*
222+
* Serialize a Server Hello Done message
223+
*/
224+
std::vector<uint8_t> Server_Hello_Done::serialize() const {
225+
return std::vector<uint8_t>();
226+
}
227+
228+
} // namespace Botan::TLS

src/lib/tls/tls12/tls_messages_12.h

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,84 @@ class PK_Key_Agreement_Key;
1919

2020
namespace Botan::TLS {
2121

22+
class BOTAN_UNSTABLE_API Server_Hello_12 final : public Server_Hello_12_Shim {
23+
public:
24+
class Settings final {
25+
public:
26+
Settings(Session_ID new_session_id,
27+
Protocol_Version new_session_version,
28+
uint16_t ciphersuite,
29+
bool offer_session_ticket) :
30+
m_new_session_id(std::move(new_session_id)),
31+
m_new_session_version(new_session_version),
32+
m_ciphersuite(ciphersuite),
33+
m_offer_session_ticket(offer_session_ticket) {}
34+
35+
const Session_ID& session_id() const { return m_new_session_id; }
36+
37+
Protocol_Version protocol_version() const { return m_new_session_version; }
38+
39+
uint16_t ciphersuite() const { return m_ciphersuite; }
40+
41+
bool offer_session_ticket() const { return m_offer_session_ticket; }
42+
43+
private:
44+
const Session_ID m_new_session_id;
45+
Protocol_Version m_new_session_version;
46+
uint16_t m_ciphersuite;
47+
bool m_offer_session_ticket;
48+
};
49+
50+
Server_Hello_12(Handshake_IO& io,
51+
Handshake_Hash& hash,
52+
const Policy& policy,
53+
Callbacks& cb,
54+
RandomNumberGenerator& rng,
55+
const std::vector<uint8_t>& secure_reneg_info,
56+
const Client_Hello_12& client_hello,
57+
const Settings& settings,
58+
std::string_view next_protocol);
59+
60+
Server_Hello_12(Handshake_IO& io,
61+
Handshake_Hash& hash,
62+
const Policy& policy,
63+
Callbacks& cb,
64+
RandomNumberGenerator& rng,
65+
const std::vector<uint8_t>& secure_reneg_info,
66+
const Client_Hello_12& client_hello,
67+
const Session& resumed_session,
68+
bool offer_session_ticket,
69+
std::string_view next_protocol);
70+
71+
explicit Server_Hello_12(const std::vector<uint8_t>& buf);
72+
73+
private:
74+
explicit Server_Hello_12(std::unique_ptr<Server_Hello_Internal> data);
75+
76+
public:
77+
using Server_Hello::compression_method;
78+
using Server_Hello::extension_types;
79+
using Server_Hello::legacy_version;
80+
using Server_Hello::random;
81+
82+
bool secure_renegotiation() const;
83+
84+
std::vector<uint8_t> renegotiation_info() const;
85+
86+
std::string next_protocol() const;
87+
88+
bool supports_extended_master_secret() const;
89+
90+
bool supports_encrypt_then_mac() const;
91+
92+
bool supports_certificate_status_message() const;
93+
94+
bool supports_session_ticket() const;
95+
96+
uint16_t srtp_profile() const;
97+
bool prefers_compressed_ec_points() const;
98+
};
99+
22100
/**
23101
* Client Key Exchange Message
24102
*/

0 commit comments

Comments
 (0)