/src/botan/src/lib/tls/msg_server_hello.cpp
Line | Count | Source (jump to first uncovered line) |
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.h> |
11 | | #include <botan/tls_extensions.h> |
12 | | #include <botan/tls_callbacks.h> |
13 | | #include <botan/internal/tls_reader.h> |
14 | | #include <botan/internal/tls_session_key.h> |
15 | | #include <botan/internal/tls_handshake_io.h> |
16 | | #include <botan/internal/tls_handshake_hash.h> |
17 | | #include <botan/internal/stl_util.h> |
18 | | |
19 | | namespace Botan { |
20 | | |
21 | | namespace TLS { |
22 | | |
23 | | namespace { |
24 | | |
25 | | const uint64_t DOWNGRADE_TLS11 = 0x444F574E47524400; |
26 | | //const uint64_t DOWNGRADE_TLS12 = 0x444F574E47524401; |
27 | | |
28 | | std::vector<uint8_t> |
29 | | make_server_hello_random(RandomNumberGenerator& rng, |
30 | | Protocol_Version offered_version, |
31 | | const Policy& policy) |
32 | 25.4k | { |
33 | 25.4k | auto random = make_hello_random(rng, policy); |
34 | 25.4k | |
35 | 25.4k | if((offered_version == Protocol_Version::TLS_V10 || |
36 | 25.4k | offered_version == Protocol_Version::TLS_V11) && |
37 | 0 | policy.allow_tls12()) |
38 | 0 | { |
39 | 0 | store_be(DOWNGRADE_TLS11, &random[24]); |
40 | 0 | } |
41 | 25.4k | |
42 | 25.4k | if(offered_version == Protocol_Version::DTLS_V10 && policy.allow_dtls12()) |
43 | 0 | { |
44 | 0 | store_be(DOWNGRADE_TLS11, &random[24]); |
45 | 0 | } |
46 | 25.4k | |
47 | 25.4k | return random; |
48 | 25.4k | } |
49 | | |
50 | | } |
51 | | |
52 | | // New session case |
53 | | Server_Hello::Server_Hello(Handshake_IO& io, |
54 | | Handshake_Hash& hash, |
55 | | const Policy& policy, |
56 | | Callbacks& cb, |
57 | | RandomNumberGenerator& rng, |
58 | | const std::vector<uint8_t>& reneg_info, |
59 | | const Client_Hello& client_hello, |
60 | | const Server_Hello::Settings& server_settings, |
61 | | const std::string next_protocol) : |
62 | | m_version(server_settings.protocol_version()), |
63 | | m_session_id(server_settings.session_id()), |
64 | | m_random(make_server_hello_random(rng, m_version, policy)), |
65 | | m_ciphersuite(server_settings.ciphersuite()), |
66 | | m_comp_method(0) |
67 | 25.4k | { |
68 | 25.4k | if(client_hello.supports_extended_master_secret()) |
69 | 6.49k | m_extensions.add(new Extended_Master_Secret); |
70 | 25.4k | |
71 | | // Sending the extension back does not commit us to sending a stapled response |
72 | 25.4k | if(client_hello.supports_cert_status_message() && policy.support_cert_status_message()) |
73 | 646 | m_extensions.add(new Certificate_Status_Request); |
74 | 25.4k | |
75 | 25.4k | Ciphersuite c = Ciphersuite::by_id(m_ciphersuite); |
76 | 25.4k | |
77 | 25.4k | if(c.cbc_ciphersuite() && client_hello.supports_encrypt_then_mac() && policy.negotiate_encrypt_then_mac()) |
78 | 434 | { |
79 | 434 | m_extensions.add(new Encrypt_then_MAC); |
80 | 434 | } |
81 | 25.4k | |
82 | 25.4k | if(c.ecc_ciphersuite() && client_hello.extension_types().count(TLSEXT_EC_POINT_FORMATS)) |
83 | 871 | { |
84 | 871 | m_extensions.add(new Supported_Point_Formats(policy.use_ecc_point_compression())); |
85 | 871 | } |
86 | 25.4k | |
87 | 25.4k | if(client_hello.secure_renegotiation()) |
88 | 7.28k | m_extensions.add(new Renegotiation_Extension(reneg_info)); |
89 | 25.4k | |
90 | 25.4k | if(client_hello.supports_session_ticket() && server_settings.offer_session_ticket()) |
91 | 1.23k | m_extensions.add(new Session_Ticket()); |
92 | 25.4k | |
93 | 25.4k | if(!next_protocol.empty() && client_hello.supports_alpn()) |
94 | 7.36k | m_extensions.add(new Application_Layer_Protocol_Notification(next_protocol)); |
95 | 25.4k | |
96 | 25.4k | if(m_version.is_datagram_protocol()) |
97 | 0 | { |
98 | 0 | const std::vector<uint16_t> server_srtp = policy.srtp_profiles(); |
99 | 0 | const std::vector<uint16_t> client_srtp = client_hello.srtp_profiles(); |
100 | 0 |
|
101 | 0 | if(!server_srtp.empty() && !client_srtp.empty()) |
102 | 0 | { |
103 | 0 | uint16_t shared = 0; |
104 | | // always using server preferences for now |
105 | 0 | for(auto s_srtp : server_srtp) |
106 | 0 | for(auto c_srtp : client_srtp) |
107 | 0 | { |
108 | 0 | if(shared == 0 && s_srtp == c_srtp) |
109 | 0 | shared = s_srtp; |
110 | 0 | } |
111 | 0 |
|
112 | 0 | if(shared) |
113 | 0 | m_extensions.add(new SRTP_Protection_Profiles(shared)); |
114 | 0 | } |
115 | 0 | } |
116 | 25.4k | |
117 | 25.4k | cb.tls_modify_extensions(m_extensions, SERVER); |
118 | 25.4k | |
119 | 25.4k | hash.update(io.send(*this)); |
120 | 25.4k | } |
121 | | |
122 | | // Resuming |
123 | | Server_Hello::Server_Hello(Handshake_IO& io, |
124 | | Handshake_Hash& hash, |
125 | | const Policy& policy, |
126 | | Callbacks& cb, |
127 | | RandomNumberGenerator& rng, |
128 | | const std::vector<uint8_t>& reneg_info, |
129 | | const Client_Hello& client_hello, |
130 | | Session& resumed_session, |
131 | | bool offer_session_ticket, |
132 | | const std::string& next_protocol) : |
133 | | m_version(resumed_session.version()), |
134 | | m_session_id(client_hello.session_id()), |
135 | | m_random(make_hello_random(rng, policy)), |
136 | | m_ciphersuite(resumed_session.ciphersuite_code()), |
137 | | m_comp_method(0) |
138 | 0 | { |
139 | 0 | if(client_hello.supports_extended_master_secret()) |
140 | 0 | m_extensions.add(new Extended_Master_Secret); |
141 | 0 |
|
142 | 0 | if(client_hello.supports_encrypt_then_mac() && policy.negotiate_encrypt_then_mac()) |
143 | 0 | { |
144 | 0 | Ciphersuite c = resumed_session.ciphersuite(); |
145 | 0 | if(c.cbc_ciphersuite()) |
146 | 0 | m_extensions.add(new Encrypt_then_MAC); |
147 | 0 | } |
148 | 0 |
|
149 | 0 | if(resumed_session.ciphersuite().ecc_ciphersuite() && client_hello.extension_types().count(TLSEXT_EC_POINT_FORMATS)) |
150 | 0 | { |
151 | 0 | m_extensions.add(new Supported_Point_Formats(policy.use_ecc_point_compression())); |
152 | 0 | } |
153 | 0 |
|
154 | 0 | if(client_hello.secure_renegotiation()) |
155 | 0 | m_extensions.add(new Renegotiation_Extension(reneg_info)); |
156 | 0 |
|
157 | 0 | if(client_hello.supports_session_ticket() && offer_session_ticket) |
158 | 0 | m_extensions.add(new Session_Ticket()); |
159 | 0 |
|
160 | 0 | if(!next_protocol.empty() && client_hello.supports_alpn()) |
161 | 0 | m_extensions.add(new Application_Layer_Protocol_Notification(next_protocol)); |
162 | 0 |
|
163 | 0 | cb.tls_modify_extensions(m_extensions, SERVER); |
164 | 0 |
|
165 | 0 | hash.update(io.send(*this)); |
166 | 0 | } |
167 | | |
168 | | /* |
169 | | * Deserialize a Server Hello message |
170 | | */ |
171 | | Server_Hello::Server_Hello(const std::vector<uint8_t>& buf) |
172 | 5.31k | { |
173 | 5.31k | if(buf.size() < 38) |
174 | 38 | throw Decoding_Error("Server_Hello: Packet corrupted"); |
175 | 5.27k | |
176 | 5.27k | TLS_Data_Reader reader("ServerHello", buf); |
177 | 5.27k | |
178 | 5.27k | const uint8_t major_version = reader.get_byte(); |
179 | 5.27k | const uint8_t minor_version = reader.get_byte(); |
180 | 5.27k | |
181 | 5.27k | m_version = Protocol_Version(major_version, minor_version); |
182 | 5.27k | |
183 | 5.27k | m_random = reader.get_fixed<uint8_t>(32); |
184 | 5.27k | |
185 | 5.27k | m_session_id = reader.get_range<uint8_t>(1, 0, 32); |
186 | 5.27k | |
187 | 5.27k | m_ciphersuite = reader.get_uint16_t(); |
188 | 5.27k | |
189 | 5.27k | m_comp_method = reader.get_byte(); |
190 | 5.27k | |
191 | 5.27k | m_extensions.deserialize(reader, Connection_Side::SERVER); |
192 | 5.27k | } |
193 | | |
194 | | /* |
195 | | * Serialize a Server Hello message |
196 | | */ |
197 | | std::vector<uint8_t> Server_Hello::serialize() const |
198 | 25.4k | { |
199 | 25.4k | std::vector<uint8_t> buf; |
200 | 25.4k | |
201 | 25.4k | buf.push_back(m_version.major_version()); |
202 | 25.4k | buf.push_back(m_version.minor_version()); |
203 | 25.4k | buf += m_random; |
204 | 25.4k | |
205 | 25.4k | append_tls_length_value(buf, m_session_id, 1); |
206 | 25.4k | |
207 | 25.4k | buf.push_back(get_byte(0, m_ciphersuite)); |
208 | 25.4k | buf.push_back(get_byte(1, m_ciphersuite)); |
209 | 25.4k | |
210 | 25.4k | buf.push_back(m_comp_method); |
211 | 25.4k | |
212 | 25.4k | buf += m_extensions.serialize(Connection_Side::SERVER); |
213 | 25.4k | |
214 | 25.4k | return buf; |
215 | 25.4k | } |
216 | | |
217 | | bool Server_Hello::random_signals_downgrade() const |
218 | 106 | { |
219 | 106 | const uint64_t last8 = load_be<uint64_t>(m_random.data(), 3); |
220 | 106 | return (last8 == DOWNGRADE_TLS11); |
221 | 106 | } |
222 | | |
223 | | /* |
224 | | * Create a new Server Hello Done message |
225 | | */ |
226 | | Server_Hello_Done::Server_Hello_Done(Handshake_IO& io, |
227 | | Handshake_Hash& hash) |
228 | 25.3k | { |
229 | 25.3k | hash.update(io.send(*this)); |
230 | 25.3k | } |
231 | | |
232 | | /* |
233 | | * Deserialize a Server Hello Done message |
234 | | */ |
235 | | Server_Hello_Done::Server_Hello_Done(const std::vector<uint8_t>& buf) |
236 | 1.53k | { |
237 | 1.53k | if(buf.size()) |
238 | 11 | throw Decoding_Error("Server_Hello_Done: Must be empty, and is not"); |
239 | 1.53k | } |
240 | | |
241 | | /* |
242 | | * Serialize a Server Hello Done message |
243 | | */ |
244 | | std::vector<uint8_t> Server_Hello_Done::serialize() const |
245 | 25.3k | { |
246 | 25.3k | return std::vector<uint8_t>(); |
247 | 25.3k | } |
248 | | |
249 | | } |
250 | | |
251 | | } |