Botan 3.11.0
Crypto and TLS for C&
msg_server_hello_12.cpp
Go to the documentation of this file.
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_12.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
19namespace Botan::TLS {
20
21// New session case
23 Handshake_Hash& hash,
24 const Policy& policy,
25 Callbacks& cb,
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
98 Handshake_Hash& hash,
99 const Policy& policy,
100 Callbacks& cb,
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
147Server_Hello_12::Server_Hello_12(const std::vector<uint8_t>& buf) :
148 Server_Hello_12(std::make_unique<Server_Hello_Internal>(buf)) {}
149
150Server_Hello_12::Server_Hello_12(std::unique_ptr<Server_Hello_Internal> data) : Server_Hello_12_Shim(std::move(data)) {}
151
153 return m_data->extensions().has<Renegotiation_Extension>();
154}
155
156std::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
164 return m_data->extensions().has<Extended_Master_Secret>();
165}
166
168 return m_data->extensions().has<Encrypt_then_MAC>();
169}
170
174
176 return m_data->extensions().has<Session_Ticket_Extension>();
177}
178
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
192 if(auto* alpn = m_data->extensions().get<Application_Layer_Protocol_Notification>()) {
193 return alpn->single_protocol();
194 }
195 return "";
196}
197
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*/
211
212/*
213* Deserialize a Server Hello Done message
214*/
215Server_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*/
224std::vector<uint8_t> Server_Hello_Done::serialize() const {
225 return std::vector<uint8_t>();
226}
227
228} // namespace Botan::TLS
static std::optional< Ciphersuite > by_id(uint16_t suite)
std::set< Extension_Code > extension_types() const
void update(const uint8_t in[], size_t length)
virtual std::vector< uint8_t > send(const Handshake_Message &msg)=0
virtual std::vector< uint8_t > serialize() const =0
virtual bool negotiate_encrypt_then_mac() const
virtual bool support_cert_status_message() const
std::vector< uint8_t > renegotiation_info() const
Server_Hello_12(Handshake_IO &io, Handshake_Hash &hash, const Policy &policy, Callbacks &cb, RandomNumberGenerator &rng, const std::vector< uint8_t > &secure_reneg_info, const Client_Hello_12 &client_hello, const Settings &settings, std::string_view next_protocol)
Server_Hello_Done(Handshake_IO &io, Handshake_Hash &hash)
const Session_ID & session_id() const
std::unique_ptr< Server_Hello_Internal > m_data
std::vector< uint8_t > make_hello_random(RandomNumberGenerator &rng, Callbacks &cb, const Policy &policy)
std::vector< uint8_t > make_server_hello_random(RandomNumberGenerator &rng, Protocol_Version offered_version, Callbacks &cb, const Policy &policy)