Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- Class List
- Class Index
- Class Hierarchy
- Class Members

Public Member Functions | List of all members
Botan::TLS::Client_Key_Exchange Class Referencefinal

`#include <tls_messages.h>`

Inheritance diagram for Botan::TLS::Client_Key_Exchange:

## Public Member Functions
| Client_Key_Exchange (Handshake_IO &io, Handshake_State &state, const Policy &policy, Credentials_Manager &creds, const Public_Key *server_public_key, const std::string &hostname, RandomNumberGenerator &rng)
| Client_Key_Exchange (const std::vector< uint8_t > &buf, const Handshake_State &state, const Private_Key *server_rsa_kex_key, Credentials_Manager &creds, const Policy &policy, RandomNumberGenerator &rng)
const secure_vector< uint8_t > & | pre_master_secret () const
Handshake_Type | type () const override
std::string | type_string () const

## Detailed Description

Client Key Exchange Message

Definition at line 397 of file tls_messages.h.

## Constructor & Destructor Documentation

Botan::TLS::Client_Key_Exchange::Client_Key_Exchange | ( | Handshake_IO & | io,
|  | Handshake_State & | state,
|  | const Policy & | policy,
|  | Credentials_Manager & | creds,
|  | const Public_Key * | server_public_key,
|  | const std::string & | hostname,
|  | RandomNumberGenerator & | rng
| ) |  |

Definition at line 44 of file msg_client_kex.cpp.

References Botan::Public_Key::algo_name(), Botan::TLS::Policy::allowed_ecc_curve(), Botan::TLS::append_tls_length_value(), Botan::OctetString::bits_of(), Botan::CECPQ1_accept(), Botan::CECPQ1_ACCEPT_BYTES, Botan::CECPQ1_OFFER_BYTES, Botan::CECPQ1_SHARED_KEY_BYTES, Botan::TLS::Policy::check_peer_key_acceptable(), Botan::TLS::Handshake_State::ciphersuite(), Botan::TLS::Handshake_State::client_hello(), Botan::PointGFp::COMPRESSED, Botan::TLS::Supported_Elliptic_Curves::curve_id_to_name(), Botan::BigInt::decode(), Botan::PK_Key_Agreement::derive_key(), Botan::BigInt::encode(), Botan::PK_Encryptor::encrypt(), Botan::EC_Group::get_curve(), Botan::TLS::TLS_Data_Reader::get_string(), Botan::TLS::Alert::HANDSHAKE_FAILURE, Botan::TLS::Handshake_State::hash(), Botan::TLS::Alert::INSUFFICIENT_SECURITY, Botan::TLS::Ciphersuite::kex_algo(), Botan::OctetString::length(), Botan::TLS::Protocol_Version::major_version(), Botan::TLS::Protocol_Version::minor_version(), Botan::OS2ECP(), Botan::Credentials_Manager::psk(), Botan::Credentials_Manager::psk_identity(), Botan::DH_PublicKey::public_value(), Botan::Curve25519_PublicKey::public_value(), Botan::ECDH_PublicKey::public_value(), Botan::DH_PrivateKey::public_value(), Botan::Curve25519_PrivateKey::public_value(), Botan::ECDH_PrivateKey::public_value(), Botan::RandomNumberGenerator::random_vec(), Botan::TLS::Handshake_IO::send(), Botan::TLS::Handshake_State::server_hello(), Botan::TLS::Handshake_State::server_kex(), Botan::srp6_client_agree(), Botan::srp6_group_identifier(), Botan::Credentials_Manager::srp_identifier(), Botan::Credentials_Manager::srp_password(), Botan::CT::strip_leading_zeros(), Botan::ASN1::to_string(), Botan::PointGFp::UNCOMPRESSED, Botan::TLS::Handshake_Hash::update(), and Botan::DL_Group::verify_group().

51 {
52 const std::string kex_algo = state.ciphersuite().kex_algo();
53
54 if(kex_algo == "PSK")
55 {
56 std::string identity_hint = "";
57
58 if(state.server_kex())
59 {
60 TLS_Data_Reader reader("ClientKeyExchange", state.server_kex()->params());
61 identity_hint = reader.get_string(2, 0, 65535);
62 }
63
64 const std::string psk_identity =
65 creds.psk_identity("tls-client", hostname, identity_hint);
66
67 append_tls_length_value(m_key_material, psk_identity, 2);
68
69 SymmetricKey psk = creds.psk("tls-client", hostname, psk_identity);
70
71 std::vector<uint8_t> zeros(psk.length());
72
73 append_tls_length_value(m_pre_master, zeros, 2);
74 append_tls_length_value(m_pre_master, psk.bits_of(), 2);
75 }
76 else if(state.server_kex())
77 {
78 TLS_Data_Reader reader("ClientKeyExchange", state.server_kex()->params());
79
80 SymmetricKey psk;
81
82 if(kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
83 {
84 std::string identity_hint = reader.get_string(2, 0, 65535);
85
86 const std::string psk_identity =
87 creds.psk_identity("tls-client", hostname, identity_hint);
88
89 append_tls_length_value(m_key_material, psk_identity, 2);
90
91 psk = creds.psk("tls-client", hostname, psk_identity);
92 }
93
94 if(kex_algo == "DH" || kex_algo == "DHE_PSK")
95 {
96 BigInt p = BigInt::decode(reader.get_range<uint8_t>(2, 1, 65535));
97 BigInt g = BigInt::decode(reader.get_range<uint8_t>(2, 1, 65535));
98 BigInt Y = BigInt::decode(reader.get_range<uint8_t>(2, 1, 65535));
99
100 if(reader.remaining_bytes())
101 throw Decoding_Error("Bad params size for DH key exchange");
102
103 /*
104 * A basic check for key validity. As we do not know q here we
105 * cannot check that Y is in the right subgroup. However since
106 * our key is ephemeral there does not seem to be any
107 * advantage to bogus keys anyway.
108 */
109 if(Y <= 1 || Y >= p - 1)
110 throw TLS_Exception(Alert::INSUFFICIENT_SECURITY,
111 "Server sent bad DH key for DHE exchange");
112
113 DL_Group group(p, g);
114
115 if(!group.verify_group(rng, false))
116 throw TLS_Exception(Alert::INSUFFICIENT_SECURITY,
117 "DH group validation failed");
118
119 DH_PublicKey counterparty_key(group, Y);
120
121 policy.check_peer_key_acceptable(counterparty_key);
122
123 DH_PrivateKey priv_key(rng, group);
124
125 PK_Key_Agreement ka(priv_key, rng, "Raw");
126
127 secure_vector<uint8_t> dh_secret = CT::strip_leading_zeros(
128 ka.derive_key(0, counterparty_key.public_value()).bits_of());
129
130 if(kex_algo == "DH")
131 m_pre_master = dh_secret;
132 else
133 {
134 append_tls_length_value(m_pre_master, dh_secret, 2);
135 append_tls_length_value(m_pre_master, psk.bits_of(), 2);
136 }
137
138 append_tls_length_value(m_key_material, priv_key.public_value(), 2);
139 }
140 else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
141 {
142 const uint8_t curve_type = reader.get_byte();
143
144 if(curve_type != 3)
145 throw Decoding_Error("Server sent non-named ECC curve");
146
147 const uint16_t curve_id = reader.get_uint16_t();
148
149 const std::string curve_name = Supported_Elliptic_Curves::curve_id_to_name(curve_id);
150
151 if(curve_name == "")
152 throw Decoding_Error("Server sent unknown named curve " + std::to_string(curve_id));
153
154 if(!policy.allowed_ecc_curve(curve_name))
155 {
156 throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
157 "Server sent ECC curve prohibited by policy");
158 }
159
160 const std::vector<uint8_t> ecdh_key = reader.get_range<uint8_t>(1, 1, 255);
161 std::vector<uint8_t> our_ecdh_public;
162 secure_vector<uint8_t> ecdh_secret;
163
164 if(curve_name == "x25519")
165 {
166 #if defined(BOTAN_HAS_CURVE_25519)
167 if(ecdh_key.size() != 32)
168 throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Invalid X25519 key size");
169
170 Curve25519_PublicKey counterparty_key(ecdh_key);
171 policy.check_peer_key_acceptable(counterparty_key);
172 Curve25519_PrivateKey priv_key(rng);
173 PK_Key_Agreement ka(priv_key, rng, "Raw");
174 ecdh_secret = ka.derive_key(0, counterparty_key.public_value()).bits_of();
175
176 // X25519 is always compressed but sent as "uncompressed" in TLS
177 our_ecdh_public = priv_key.public_value();
178 #else
179 throw Internal_Error("Negotiated X25519 somehow, but it is disabled");
180 #endif
181 }
182 else
183 {
184 EC_Group group(curve_name);
185 ECDH_PublicKey counterparty_key(group, OS2ECP(ecdh_key, group.get_curve()));
186 policy.check_peer_key_acceptable(counterparty_key);
187 ECDH_PrivateKey priv_key(rng, group);
188 PK_Key_Agreement ka(priv_key, rng, "Raw");
189 ecdh_secret = ka.derive_key(0, counterparty_key.public_value()).bits_of();
190
191 // follow server's preference for point compression
192 our_ecdh_public = priv_key.public_value(
193 state.server_hello()->prefers_compressed_ec_points() ? PointGFp::COMPRESSED : PointGFp::UNCOMPRESSED);
194 }
195
196 if(kex_algo == "ECDH")
197 m_pre_master = ecdh_secret;
198 else
199 {
200 append_tls_length_value(m_pre_master, ecdh_secret, 2);
201 append_tls_length_value(m_pre_master, psk.bits_of(), 2);
202 }
203
204 append_tls_length_value(m_key_material, our_ecdh_public, 1);
205 }
206 #if defined(BOTAN_HAS_SRP6)
207 else if(kex_algo == "SRP_SHA")
208 {
209 const BigInt N = BigInt::decode(reader.get_range<uint8_t>(2, 1, 65535));
210 const BigInt g = BigInt::decode(reader.get_range<uint8_t>(2, 1, 65535));
211 std::vector<uint8_t> salt = reader.get_range<uint8_t>(1, 1, 255);
212 const BigInt B = BigInt::decode(reader.get_range<uint8_t>(2, 1, 65535));
213
214 const std::string srp_group = srp6_group_identifier(N, g);
215
216 const std::string srp_identifier =
217 creds.srp_identifier("tls-client", hostname);
218
219 const std::string srp_password =
220 creds.srp_password("tls-client", hostname, srp_identifier);
221
222 std::pair<BigInt, SymmetricKey> srp_vals =
223 srp6_client_agree(srp_identifier,
224 srp_password,
225 srp_group,
226 "SHA-1",
227 salt,
228 B,
229 rng);
230
231 append_tls_length_value(m_key_material, BigInt::encode(srp_vals.first), 2);
232 m_pre_master = srp_vals.second.bits_of();
233 }
234 #endif
235
236 #if defined(BOTAN_HAS_CECPQ1)
237 else if(kex_algo == "CECPQ1")
238 {
239 const std::vector<uint8_t> cecpq1_offer = reader.get_range<uint8_t>(2, 1, 65535);
240
241 if(cecpq1_offer.size() != CECPQ1_OFFER_BYTES)
242 throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Invalid CECPQ1 key size");
243
244 std::vector<uint8_t> newhope_accept(CECPQ1_ACCEPT_BYTES);
245 secure_vector<uint8_t> shared_secret(CECPQ1_SHARED_KEY_BYTES);
246 CECPQ1_accept(shared_secret.data(), newhope_accept.data(), cecpq1_offer.data(), rng);
247 append_tls_length_value(m_key_material, newhope_accept, 2);
248 m_pre_master = shared_secret;
249 }
250 #endif
251 else
252 {
253 throw Internal_Error("Client_Key_Exchange: Unknown kex " + kex_algo);
254 }
255
256 reader.assert_done();
257 }
258 else
259 {
260 // No server key exchange msg better mean RSA kex + RSA key in cert
261
262 if(kex_algo != "RSA")
263 throw Unexpected_Message("No server kex but negotiated kex " + kex_algo);
264
265 if(!server_public_key)
266 throw Internal_Error("No server public key for RSA exchange");
267
268 if(auto rsa_pub = dynamic_cast<const RSA_PublicKey*>(server_public_key))
269 {
270 const Protocol_Version offered_version = state.client_hello()->version();
271
272 m_pre_master = rng.random_vec(48);
273 m_pre_master[0] = offered_version.major_version();
274 m_pre_master[1] = offered_version.minor_version();
275
276 PK_Encryptor_EME encryptor(*rsa_pub, rng, "PKCS1v15");
277
278 const std::vector<uint8_t> encrypted_key = encryptor.encrypt(m_pre_master, rng);
279
280 append_tls_length_value(m_key_material, encrypted_key, 2);
281 }
282 else
283 throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
284 "Expected a RSA key in server cert but got " +
285 server_public_key->algo_name());
286 }
287
288 state.hash().update(io.send(*this));
289 }
Botan::PointGFp::COMPRESSED
Definition: point_gfp.h:46
Botan::CECPQ1_OFFER_BYTES
Definition: newhope.h:41
Botan::PointGFp::UNCOMPRESSED
Definition: point_gfp.h:45
Botan::ASN1::to_string
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:47
Botan::TLS::Supported_Elliptic_Curves::curve_id_to_name
static std::string curve_id_to_name(uint16_t id)
Definition: tls_extensions.cpp:280
Botan::TLS::Alert::HANDSHAKE_FAILURE
Definition: tls_alert.h:34
Botan::OS2ECP
PointGFp OS2ECP(const uint8_t data[], size_t data_len, const CurveGFp &curve)
Definition: point_gfp.cpp:544
Botan::TLS::Alert::INSUFFICIENT_SECURITY
Definition: tls_alert.h:48
Botan::CECPQ1_accept
void CECPQ1_accept(uint8_t shared_key[CECPQ1_SHARED_KEY_BYTES], uint8_t send[CECPQ1_ACCEPT_BYTES], const uint8_t received[CECPQ1_OFFER_BYTES], RandomNumberGenerator &rng)
Definition: cecpq1.cpp:25
Botan::SymmetricKey
OctetString SymmetricKey
Definition: symkey.h:136
Botan::srp6_client_agree
std::pair< BigInt, SymmetricKey > srp6_client_agree(const std::string &identifier, const std::string &password, const std::string &group_id, const std::string &hash_id, const std::vector< uint8_t > &salt, const BigInt &B, RandomNumberGenerator &rng)
Definition: srp6.cpp:76
server_public_key
std::unique_ptr< Public_Key > server_public_key
Definition: tls_client.cpp:40
Botan::CECPQ1_SHARED_KEY_BYTES
Definition: newhope.h:43
Botan::CECPQ1_ACCEPT_BYTES
Definition: newhope.h:42
Botan::BigInt::encode
static std::vector< uint8_t > encode(const BigInt &n, Base base=Binary)
Definition: big_code.cpp:54
Botan::srp6_group_identifier
std::string srp6_group_identifier(const BigInt &N, const BigInt &g)
Definition: srp6.cpp:52
Botan::BigInt::decode
static BigInt decode(const uint8_t buf[], size_t length, Base base=Binary)
Definition: big_code.cpp:114
Botan::CT::strip_leading_zeros
secure_vector< uint8_t > strip_leading_zeros(const uint8_t in[], size_t length)
Definition: ct_utils.h:186
Botan::TLS::append_tls_length_value
void append_tls_length_value(std::vector< uint8_t, Alloc > &buf, const T *vals, size_t vals_size, size_t tag_size)
Definition: tls_reader.h:185

Botan::TLS::Client_Key_Exchange::Client_Key_Exchange | ( | const std::vector< uint8_t > & | buf,
|  | const Handshake_State & | state,
|  | const Private_Key * | server_rsa_kex_key,
|  | Credentials_Manager & | creds,
|  | const Policy & | policy,
|  | RandomNumberGenerator & | rng
| ) |  |

Definition at line 294 of file msg_client_kex.cpp.

References Botan::Public_Key::algo_name(), Botan::TLS::append_tls_length_value(), Botan::OctetString::bits_of(), BOTAN_ASSERT, Botan::CECPQ1_ACCEPT_BYTES, Botan::CECPQ1_finish(), Botan::CECPQ1_SHARED_KEY_BYTES, Botan::TLS::Handshake_State::ciphersuite(), Botan::TLS::Handshake_State::client_hello(), Botan::BigInt::decode(), Botan::PK_Key_Agreement::derive_key(), Botan::TLS::TLS_Data_Reader::get_range(), Botan::TLS::TLS_Data_Reader::get_string(), Botan::TLS::Policy::hide_unknown_users(), Botan::TLS::Ciphersuite::kex_algo(), Botan::OctetString::length(), Botan::Credentials_Manager::psk(), Botan::PK_Key_Agreement_Key::public_value(), Botan::RandomNumberGenerator::random_vec(), Botan::TLS::Handshake_State::server_certs(), Botan::TLS::Handshake_State::server_kex(), Botan::SRP6_Server_Session::step2(), Botan::CT::strip_leading_zeros(), and Botan::TLS::Alert::UNKNOWN_PSK_IDENTITY.

300 {
301 const std::string kex_algo = state.ciphersuite().kex_algo();
302
303 if(kex_algo == "RSA")
304 {
305 BOTAN_ASSERT(state.server_certs() && !state.server_certs()->cert_chain().empty(),
306 "RSA key exchange negotiated so server sent a certificate");
307
308 if(!server_rsa_kex_key)
309 throw Internal_Error("Expected RSA kex but no server kex key set");
310
311 if(!dynamic_cast<const RSA_PrivateKey*>(server_rsa_kex_key))
312 throw Internal_Error("Expected RSA key but got " + server_rsa_kex_key->algo_name());
313
314 TLS_Data_Reader reader("ClientKeyExchange", contents);
315 const std::vector<uint8_t> encrypted_pre_master = reader.get_range<uint8_t>(2, 0, 65535);
316
317 PK_Decryptor_EME decryptor(*server_rsa_kex_key, rng, "PKCS1v15");
318
319 const uint8_t client_major = state.client_hello()->version().major_version();
320 const uint8_t client_minor = state.client_hello()->version().minor_version();
321
322 /*
323 * PK_Decryptor::decrypt_or_random will return a random value if
324 * either the length does not match the expected value or if the
325 * version number embedded in the PMS does not match the one sent
326 * in the client hello.
327 */
328 const size_t expected_plaintext_size = 48;
329 const size_t expected_content_size = 2;
330 const uint8_t expected_content_bytes[expected_content_size] = { client_major, client_minor };
331 const uint8_t expected_content_pos[expected_content_size] = { 0, 1 };
332
333 m_pre_master =
334 decryptor.decrypt_or_random(encrypted_pre_master.data(),
335 encrypted_pre_master.size(),
336 expected_plaintext_size,
337 rng,
338 expected_content_bytes,
339 expected_content_pos,
340 expected_content_size);
341 }
342 else
343 {
344 TLS_Data_Reader reader("ClientKeyExchange", contents);
345
346 SymmetricKey psk;
347
348 if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
349 {
350 const std::string psk_identity = reader.get_string(2, 0, 65535);
351
352 psk = creds.psk("tls-server",
353 state.client_hello()->sni_hostname(),
354 psk_identity);
355
356 if(psk.length() == 0)
357 {
358 if(policy.hide_unknown_users())
359 psk = SymmetricKey(rng, 16);
360 else
361 throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY,
362 "No PSK for identifier " + psk_identity);
363 }
364 }
365
366 if(kex_algo == "PSK")
367 {
368 std::vector<uint8_t> zeros(psk.length());
369 append_tls_length_value(m_pre_master, zeros, 2);
370 append_tls_length_value(m_pre_master, psk.bits_of(), 2);
371 }
372 #if defined(BOTAN_HAS_SRP6)
373 else if(kex_algo == "SRP_SHA")
374 {
375 SRP6_Server_Session& srp = state.server_kex()->server_srp_params();
376
377 m_pre_master = srp.step2(BigInt::decode(reader.get_range<uint8_t>(2, 0, 65535))).bits_of();
378 }
379 #endif
380 #if defined(BOTAN_HAS_CECPQ1)
381 else if(kex_algo == "CECPQ1")
382 {
383 const CECPQ1_key& cecpq1_offer = state.server_kex()->cecpq1_key();
384
385 const std::vector<uint8_t> cecpq1_accept = reader.get_range<uint8_t>(2, 0, 65535);
386 if(cecpq1_accept.size() != CECPQ1_ACCEPT_BYTES)
387 throw Decoding_Error("Invalid size for CECPQ1 accept message");
388
389 m_pre_master.resize(CECPQ1_SHARED_KEY_BYTES);
390 CECPQ1_finish(m_pre_master.data(), cecpq1_offer, cecpq1_accept.data());
391 }
392 #endif
393 else if(kex_algo == "DH" || kex_algo == "DHE_PSK" ||
394 kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
395 {
396 const Private_Key& private_key = state.server_kex()->server_kex_key();
397
398 const PK_Key_Agreement_Key* ka_key =
399 dynamic_cast<const PK_Key_Agreement_Key*>(&private_key);
400
401 if(!ka_key)
402 throw Internal_Error("Expected key agreement key type but got " +
403 private_key.algo_name());
404
405 try
406 {
407 PK_Key_Agreement ka(*ka_key, rng, "Raw");
408
409 std::vector<uint8_t> client_pubkey;
410
411 if(ka_key->algo_name() == "DH")
412 client_pubkey = reader.get_range<uint8_t>(2, 0, 65535);
413 else
414 client_pubkey = reader.get_range<uint8_t>(1, 0, 255);
415
416 secure_vector<uint8_t> shared_secret = ka.derive_key(0, client_pubkey).bits_of();
417
418 if(ka_key->algo_name() == "DH")
419 shared_secret = CT::strip_leading_zeros(shared_secret);
420
421 if(kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
422 {
423 append_tls_length_value(m_pre_master, shared_secret, 2);
424 append_tls_length_value(m_pre_master, psk.bits_of(), 2);
425 }
426 else
427 m_pre_master = shared_secret;
428 }
429 catch(std::exception &)
430 {
431 /*
432 * Something failed in the DH computation. To avoid possible
433 * timing attacks, randomize the pre-master output and carry
434 * on, allowing the protocol to fail later in the finished
435 * checks.
436 */
437 m_pre_master = rng.random_vec(ka_key->public_value().size());
438 }
439 }
440 else
441 throw Internal_Error("Client_Key_Exchange: Unknown kex type " + kex_algo);
442 }
443 }
Botan::CECPQ1_finish
void CECPQ1_finish(uint8_t shared_key[CECPQ1_SHARED_KEY_BYTES], const CECPQ1_key &offer_key, const uint8_t received[CECPQ1_ACCEPT_BYTES])
Definition: cecpq1.cpp:40
Botan::TLS::Alert::UNKNOWN_PSK_IDENTITY
Definition: tls_alert.h:58
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:27
Botan::SymmetricKey
OctetString SymmetricKey
Definition: symkey.h:136
Botan::CECPQ1_SHARED_KEY_BYTES
Definition: newhope.h:43
Botan::CECPQ1_ACCEPT_BYTES
Definition: newhope.h:42
Botan::BigInt::decode
static BigInt decode(const uint8_t buf[], size_t length, Base base=Binary)
Definition: big_code.cpp:114
Botan::CT::strip_leading_zeros
secure_vector< uint8_t > strip_leading_zeros(const uint8_t in[], size_t length)
Definition: ct_utils.h:186
Botan::TLS::append_tls_length_value
void append_tls_length_value(std::vector< uint8_t, Alloc > &buf, const T *vals, size_t vals_size, size_t tag_size)
Definition: tls_reader.h:185

## Member Function Documentation

const secure_vector<uint8_t>& Botan::TLS::Client_Key_Exchange::pre_master_secret | ( |  | ) | const
| inline

Definition at line 402 of file tls_messages.h.

403 { return m_pre_master; }

Handshake_Type Botan::TLS::Client_Key_Exchange::type | ( |  | ) | const
| inline override virtual

Returns
  the message type

Implements Botan::TLS::Handshake_Message.

Definition at line 400 of file tls_messages.h.

References Botan::TLS::CLIENT_KEX.

400 { return CLIENT_KEX; }
Botan::TLS::CLIENT_KEX
Definition: tls_magic.h:49

std::string Botan::TLS::Handshake_Message::type_string | ( |  | ) | const
| inherited

Returns
  string representation of this message type

Definition at line 17 of file tls_handshake_state.cpp.

References Botan::TLS::handshake_type_to_string(), and Botan::TLS::Handshake_Message::type().

18 {
19 return handshake_type_to_string(type());
20 }
Botan::TLS::Handshake_Message::type
virtual Handshake_Type type() const =0
Botan::TLS::handshake_type_to_string
const char * handshake_type_to_string(Handshake_Type type)
Definition: tls_handshake_state.cpp:22

The documentation for this class was generated from the following files:

- src/lib/tls/tls_messages.h
- src/lib/tls/msg_client_kex.cpp