Botan: src/ssl/tls_client.cpp Source File

Botan 1.10.17

tls_client.cpp
Go to the documentation of this file.
1 /*
2 * TLS Client
3 * (C) 2004-2010 Jack Lloyd
4 *
5 * Released under the terms of the Botan license
6 */
7
8 #include <botan/tls_client.h>
9 #include <botan/internal/tls_alerts.h>
10 #include <botan/internal/tls_state.h>
11 #include <botan/loadstor.h>
12 #include <botan/rsa.h>
13 #include <botan/dsa.h>
14 #include <botan/dh.h>
15
16 namespace Botan {
17
18 namespace {
19
20 /**
21 * Verify the state transition is allowed
22 * FIXME: checks are wrong for session reuse (add a flag for that)
23 */
24 void client_check_state(Handshake_Type new_msg, Handshake_State* state)
25 {
26 class State_Transition_Error : public Unexpected_Message
27 {
28 public:
29 State_Transition_Error(const std::string& err) :
30 Unexpected_Message("State transition error from " + err) {}
31 };
32
33 if(new_msg == HELLO_REQUEST)
34 {
35 if(state->client_hello)
36 throw State_Transition_Error("HelloRequest");
37 }
38 else if(new_msg == SERVER_HELLO)
39 {
40 if(!state->client_hello || state->server_hello)
41 throw State_Transition_Error("ServerHello");
42 }
43 else if(new_msg == CERTIFICATE)
44 {
45 if(!state->server_hello || state->server_kex ||
46 state->cert_req || state->server_hello_done)
47 throw State_Transition_Error("ServerCertificate");
48 }
49 else if(new_msg == SERVER_KEX)
50 {
51 if(!state->server_hello || state->server_kex ||
52 state->cert_req || state->server_hello_done)
53 throw State_Transition_Error("ServerKeyExchange");
54 }
55 else if(new_msg == CERTIFICATE_REQUEST)
56 {
57 if(!state->server_certs || state->cert_req || state->server_hello_done)
58 throw State_Transition_Error("CertificateRequest");
59 }
60 else if(new_msg == SERVER_HELLO_DONE)
61 {
62 if(!state->server_hello || state->server_hello_done)
63 throw State_Transition_Error("ServerHelloDone");
64 }
65 else if(new_msg == HANDSHAKE_CCS)
66 {
67 if(!state->client_finished || state->server_finished)
68 throw State_Transition_Error("ServerChangeCipherSpec");
69 }
70 else if(new_msg == FINISHED)
71 {
72 if(!state->got_server_ccs)
73 throw State_Transition_Error("ServerFinished");
74 }
75 else
76 throw Unexpected_Message("Unexpected message in handshake");
77 }
78
79 }
80
81 /**
82 * TLS Client Constructor
83 */
84 TLS_Client::TLS_Client(std::tr1::function<size_t (byte[], size_t)> input_fn,
85 std::tr1::function<void (const byte[], size_t)> output_fn,
86 const TLS_Policy& policy,
87 RandomNumberGenerator& rng) :
88 input_fn(input_fn),
89 policy(policy),
90 rng(rng),
91 writer(output_fn)
92 {
93 initialize();
94 }
95
96 void TLS_Client::add_client_cert(const X509_Certificate& cert,
97 Private_Key* cert_key)
98 {
99 certs.push_back(std::make_pair(cert, cert_key));
100 }
101
102 /**
103 * TLS Client Destructor
104 */
105 TLS_Client::~TLS_Client()
106 {
107 close();
108 for(size_t i = 0; i != certs.size(); i++)
109 delete certs[i].second;
110 delete state;
111 }
112
113 /**
114 * Initialize a TLS client connection
115 */
116 void TLS_Client::initialize()
117 {
118 std::string error_str;
119 Alert_Type error_type = NO_ALERT_TYPE;
120
121 try {
122 state = 0;
123 active = false;
124 writer.set_version(policy.pref_version());
125 do_handshake();
126 }
127 catch(TLS_Exception& e)
128 {
129 error_str = e.what();
130 error_type = e.type();
131 }
132 catch(std::exception& e)
133 {
134 error_str = e.what();
135 error_type = HANDSHAKE_FAILURE;
136 }
137
138 if(error_type != NO_ALERT_TYPE)
139 {
140 if(active)
141 {
142 active = false;
143 reader.reset();
144
145 writer.alert(FATAL, error_type);
146 writer.reset();
147 }
148
149 if(state)
150 {
151 delete state;
152 state = 0;
153 }
154
155 throw Stream_IO_Error("TLS_Client: Handshake failed: " + error_str);
156 }
157 }
158
159 /**
160 * Return the peer's certificate chain
161 */
162 std::vector<X509_Certificate> TLS_Client::peer_cert_chain() const
163 {
164 return peer_certs;
165 }
166
167 /**
168 * Write to a TLS connection
169 */
170 void TLS_Client::write(const byte buf[], size_t length)
171 {
172 if(!active)
173 throw TLS_Exception(INTERNAL_ERROR,
174 "TLS_Client::write called while closed");
175
176 writer.send(APPLICATION_DATA, buf, length);
177 }
178
179 /**
180 * Read from a TLS connection
181 */
182 size_t TLS_Client::read(byte out[], size_t length)
183 {
184 if(!active)
185 return 0;
186
187 writer.flush();
188
189 while(read_buf.size() == 0)
190 {
191 state_machine();
192 if(active == false)
193 break;
194 }
195
196 size_t got = std::min<size_t>(read_buf.size(), length);
197 read_buf.read(out, got);
198 return got;
199 }
200
201 /**
202 * Close a TLS connection
203 */
204 void TLS_Client::close()
205 {
206 close(WARNING, CLOSE_NOTIFY);
207 }
208
209 /**
210 * Check connection status
211 */
212 bool TLS_Client::is_closed() const
213 {
214 if(!active)
215 return true;
216 return false;
217 }
218
219 /**
220 * Close a TLS connection
221 */
222 void TLS_Client::close(Alert_Level level, Alert_Type alert_code)
223 {
224 if(active)
225 {
226 try {
227 writer.alert(level, alert_code);
228 writer.flush();
229 }
230 catch(...) {}
231
232 active = false;
233 }
234 }
235
236 /**
237 * Iterate the TLS state machine
238 */
239 void TLS_Client::state_machine()
240 {
241 byte rec_type = CONNECTION_CLOSED;
242 SecureVector<byte> record(1024);
243
244 size_t bytes_needed = reader.get_record(rec_type, record);
245
246 while(bytes_needed)
247 {
248 size_t to_get = std::min<size_t>(record.size(), bytes_needed);
249 size_t got = input_fn(&record[0], to_get);
250
251 if(got == 0)
252 {
253 rec_type = CONNECTION_CLOSED;
254 break;
255 }
256
257 reader.add_input(&record[0], got);
258
259 bytes_needed = reader.get_record(rec_type, record);
260 }
261
262 if(rec_type == CONNECTION_CLOSED)
263 {
264 active = false;
265 reader.reset();
266 writer.reset();
267 }
268 else if(rec_type == APPLICATION_DATA)
269 {
270 if(active)
271 read_buf.write(&record[0], record.size());
272 else
273 throw Unexpected_Message("Application data before handshake done");
274 }
275 else if(rec_type == HANDSHAKE || rec_type == CHANGE_CIPHER_SPEC)
276 read_handshake(rec_type, record);
277 else if(rec_type == ALERT)
278 {
279 Alert alert(record);
280
281 if(alert.is_fatal() || alert.type() == CLOSE_NOTIFY)
282 {
283 if(alert.type() == CLOSE_NOTIFY)
284 writer.alert(WARNING, CLOSE_NOTIFY);
285
286 reader.reset();
287 writer.reset();
288 active = false;
289 if(state)
290 {
291 delete state;
292 state = 0;
293 }
294 }
295 }
296 else
297 throw Unexpected_Message("Unknown message type received");
298 }
299
300 /**
301 * Split up and process handshake messages
302 */
303 void TLS_Client::read_handshake(byte rec_type,
304 const MemoryRegion<byte>& rec_buf)
305 {
306 if(rec_type == HANDSHAKE)
307 {
308 if(!state)
309 return;
310
311 state->queue.write(&rec_buf[0], rec_buf.size());
312 }
313
314 while(true)
315 {
316 Handshake_Type type = HANDSHAKE_NONE;
317 SecureVector<byte> contents;
318
319 if(rec_type == HANDSHAKE)
320 {
321 if(state->queue.size() >= 4)
322 {
323 byte head[4] = { 0 };
324 state->queue.peek(head, 4);
325
326 const size_t length = make_u32bit(0, head[1], head[2], head[3]);
327
328 if(state->queue.size() >= length + 4)
329 {
330 type = static_cast<Handshake_Type>(head[0]);
331 contents.resize(length);
332 state->queue.read(head, 4);
333 state->queue.read(&contents[0], contents.size());
334 }
335 }
336 }
337 else if(rec_type == CHANGE_CIPHER_SPEC)
338 {
339 if(state->queue.size() == 0 && rec_buf.size() == 1 && rec_buf[0] == 1)
340 type = HANDSHAKE_CCS;
341 else
342 throw Decoding_Error("Malformed ChangeCipherSpec message");
343 }
344 else
345 throw Decoding_Error("Unknown message type in handshake processing");
346
347 if(type == HANDSHAKE_NONE)
348 break;
349
350 process_handshake_msg(type, contents);
351
352 if(type == HANDSHAKE_CCS || !state)
353 break;
354 }
355 }
356
357 /**
358 * Process a handshake message
359 */
360 void TLS_Client::process_handshake_msg(Handshake_Type type,
361 const MemoryRegion<byte>& contents)
362 {
363 if(type == HELLO_REQUEST)
364 return;
365
366 if(state == 0)
367 throw Unexpected_Message("Unexpected handshake message");
368
369 if(type != HANDSHAKE_CCS && type != HELLO_REQUEST && type != FINISHED)
370 {
371 state->hash.update(static_cast<byte>(type));
372 const size_t record_length = contents.size();
373 for(size_t i = 0; i != 3; i++)
374 state->hash.update(get_byte<u32bit>(i+1, record_length));
375 state->hash.update(contents);
376 }
377
378 if(type == SERVER_HELLO)
379 {
380 client_check_state(type, state);
381
382 state->server_hello = new Server_Hello(contents);
383
384 if(!state->client_hello->offered_suite(
385 state->server_hello->ciphersuite()
386 )
387 )
388 throw TLS_Exception(HANDSHAKE_FAILURE,
389 "TLS_Client: Server replied with bad ciphersuite");
390
391 state->version = state->server_hello->version();
392
393 if(state->version > state->client_hello->version())
394 throw TLS_Exception(HANDSHAKE_FAILURE,
395 "TLS_Client: Server replied with bad version");
396
397 if(state->version < policy.min_version())
398 throw TLS_Exception(PROTOCOL_VERSION,
399 "TLS_Client: Server is too old for specified policy");
400
401 writer.set_version(state->version);
402 reader.set_version(state->version);
403
404 state->suite = CipherSuite(state->server_hello->ciphersuite());
405 }
406 else if(type == CERTIFICATE)
407 {
408 client_check_state(type, state);
409
410 if(state->suite.sig_type() == TLS_ALGO_SIGNER_ANON)
411 throw Unexpected_Message("Recived certificate from anonymous server");
412
413 state->server_certs = new Certificate(contents);
414
415 peer_certs = state->server_certs->cert_chain();
416 if(peer_certs.size() == 0)
417 throw TLS_Exception(HANDSHAKE_FAILURE,
418 "TLS_Client: No certificates sent by server");
419
420 if(!policy.check_cert(peer_certs))
421 throw TLS_Exception(BAD_CERTIFICATE,
422 "TLS_Client: Server certificate is not valid");
423
424 state->kex_pub = peer_certs[0].subject_public_key();
425
426 bool is_dsa = false, is_rsa = false;
427
428 if(dynamic_cast<DSA_PublicKey*>(state->kex_pub))
429 is_dsa = true;
430 else if(dynamic_cast<RSA_PublicKey*>(state->kex_pub))
431 is_rsa = true;
432 else
433 throw TLS_Exception(UNSUPPORTED_CERTIFICATE,
434 "Unknown key type received in server kex");
435
436 if((is_dsa && state->suite.sig_type() != TLS_ALGO_SIGNER_DSA) ||
437 (is_rsa && state->suite.sig_type() != TLS_ALGO_SIGNER_RSA))
438 throw TLS_Exception(ILLEGAL_PARAMETER,
439 "Certificate key type did not match ciphersuite");
440 }
441 else if(type == SERVER_KEX)
442 {
443 client_check_state(type, state);
444
445 if(state->suite.kex_type() == TLS_ALGO_KEYEXCH_NOKEX)
446 throw Unexpected_Message("Unexpected key exchange from server");
447
448 state->server_kex = new Server_Key_Exchange(contents);
449
450 if(state->kex_pub)
451 delete state->kex_pub;
452
453 state->kex_pub = state->server_kex->key();
454
455 bool is_dh = false, is_rsa = false;
456
457 if(dynamic_cast<DH_PublicKey*>(state->kex_pub))
458 is_dh = true;
459 else if(dynamic_cast<RSA_PublicKey*>(state->kex_pub))
460 is_rsa = true;
461 else
462 throw TLS_Exception(HANDSHAKE_FAILURE,
463 "Unknown key type received in server kex");
464
465 if((is_dh && state->suite.kex_type() != TLS_ALGO_KEYEXCH_DH) ||
466 (is_rsa && state->suite.kex_type() != TLS_ALGO_KEYEXCH_RSA))
467 throw TLS_Exception(ILLEGAL_PARAMETER,
468 "Certificate key type did not match ciphersuite");
469
470 if(state->suite.sig_type() != TLS_ALGO_SIGNER_ANON)
471 {
472 if(!state->server_kex->verify(peer_certs[0],
473 state->client_hello->random(),
474 state->server_hello->random()))
475 throw TLS_Exception(DECRYPT_ERROR,
476 "Bad signature on server key exchange");
477 }
478 }
479 else if(type == CERTIFICATE_REQUEST)
480 {
481 client_check_state(type, state);
482
483 state->cert_req = new Certificate_Req(contents);
484 state->do_client_auth = true;
485 }
486 else if(type == SERVER_HELLO_DONE)
487 {
488 client_check_state(type, state);
489
490 state->server_hello_done = new Server_Hello_Done(contents);
491
492 if(state->do_client_auth)
493 {
494 std::vector<X509_Certificate> send_certs;
495
496 std::vector<Certificate_Type> types =
497 state->cert_req->acceptable_types();
498
499 // FIXME: Fill in useful certs here, if any
500 state->client_certs = new Certificate(writer, send_certs,
501 state->hash);
502 }
503
504 state->client_kex =
505 new Client_Key_Exchange(rng, writer, state->hash,
506 state->kex_pub, state->version,
507 state->client_hello->version());
508
509 if(state->do_client_auth)
510 {
511 Private_Key* key_matching_cert = 0; // FIXME
512 state->client_verify = new Certificate_Verify(rng,
513 writer, state->hash,
514 key_matching_cert);
515 }
516
517 state->keys = SessionKeys(state->suite, state->version,
518 state->client_kex->pre_master_secret(),
519 state->client_hello->random(),
520 state->server_hello->random());
521
522 writer.send(CHANGE_CIPHER_SPEC, 1);
523 writer.flush();
524
525 writer.set_keys(state->suite, state->keys, CLIENT);
526
527 state->client_finished = new Finished(writer, state->version, CLIENT,
528 state->keys.master_secret(),
529 state->hash);
530 }
531 else if(type == HANDSHAKE_CCS)
532 {
533 client_check_state(type, state);
534
535 reader.set_keys(state->suite, state->keys, CLIENT);
536 state->got_server_ccs = true;
537 }
538 else if(type == FINISHED)
539 {
540 client_check_state(type, state);
541
542 state->server_finished = new Finished(contents);
543
544 if(!state->server_finished->verify(state->keys.master_secret(),
545 state->version, state->hash, SERVER))
546 throw TLS_Exception(DECRYPT_ERROR,
547 "Finished message didn't verify");
548
549 delete state;
550 state = 0;
551 active = true;
552 }
553 else
554 throw Unexpected_Message("Unknown handshake message received");
555 }
556
557 /**
558 * Perform a client-side TLS handshake
559 */
560 void TLS_Client::do_handshake()
561 {
562 state = new Handshake_State;
563
564 state->client_hello = new Client_Hello(rng, writer, policy, state->hash);
565
566 while(true)
567 {
568 if(active && !state)
569 break;
570 if(!active && !state)
571 throw TLS_Exception(HANDSHAKE_FAILURE, "TLS_Client: Handshake failed (do_handshake)");
572
573 state_machine();
574 }
575 }
576
577 }
Botan::Record_Reader::get_record
size_t get_record(byte &msg_type, MemoryRegion< byte > &buffer)
Definition: rec_read.cpp:119
Botan::SecureQueue::size
size_t size() const
Definition: secqueue.cpp:190
Botan::ALERT
Definition: tls_magic.h:35
Botan::SecureQueue::read
size_t read(byte[], size_t)
Definition: secqueue.cpp:137
Botan::TLS_ALGO_SIGNER_DSA
Definition: tls_magic.h:149
Botan::TLS_Client::is_closed
bool is_closed() const
Definition: tls_client.cpp:212
Botan::RandomNumberGenerator
Definition: rng.h:20
Botan::TLS_ALGO_KEYEXCH_NOKEX
Definition: tls_magic.h:153
Botan::Private_Key
Definition: pk_keys.h:86
Botan::TLS_Policy::check_cert
virtual bool check_cert(const std::vector< X509_Certificate > &cert_chain) const =0
Botan::Record_Reader::add_input
void add_input(const byte input[], size_t input_size)
Definition: rec_read.cpp:111
Botan::SERVER
Definition: tls_magic.h:29
Botan::NO_ALERT_TYPE
Definition: tls_magic.h:89
Botan::HANDSHAKE_FAILURE
Definition: tls_magic.h:69
Botan::FINISHED
Definition: tls_magic.h:51
Botan::CERTIFICATE_REQUEST
Definition: tls_magic.h:47
Botan::TLS_Client::peer_cert_chain
std::vector< X509_Certificate > peer_cert_chain() const
Definition: tls_client.cpp:162
Botan::Record_Writer::set_version
void set_version(Version_Code)
Definition: rec_wri.cpp:51
Botan::WARNING
Definition: tls_magic.h:58
Botan::HANDSHAKE
Definition: tls_magic.h:36
Botan::TLS_Exception
Definition: tls_exceptn.h:19
Botan::TLS_Policy::pref_version
virtual Version_Code pref_version() const
Definition: tls_policy.h:50
Botan::Record_Writer::set_keys
void set_keys(const CipherSuite &, const SessionKeys &, Connection_Side)
Definition: rec_wri.cpp:63
Botan::SERVER_KEX
Definition: tls_magic.h:46
Botan::Handshake_Type
Handshake_Type
Definition: tls_magic.h:40
Botan::Record_Reader::set_version
void set_version(Version_Code version)
Definition: rec_read.cpp:34
Botan::UNSUPPORTED_CERTIFICATE
Definition: tls_magic.h:71
Botan::byte
unsigned char byte
Definition: types.h:22
Botan::Alert_Level
Alert_Level
Definition: tls_magic.h:57
Botan::TLS_Client::TLS_Client
TLS_Client(std::tr1::function< size_t(byte[], size_t)> input_fn, std::tr1::function< void(const byte[], size_t)> output_fn, const TLS_Policy &policy, RandomNumberGenerator &rng)
Definition: tls_client.cpp:84
Botan::TLS_Client::add_client_cert
void add_client_cert(const X509_Certificate &cert, Private_Key *cert_key)
Definition: tls_client.cpp:96
Botan::X509_Certificate
Definition: x509cert.h:23
Botan::TLS_Policy::min_version
virtual Version_Code min_version() const
Definition: tls_policy.h:45
Botan::Record_Reader::reset
void reset()
Definition: rec_read.cpp:17
Botan::PROTOCOL_VERSION
Definition: tls_magic.h:81
Botan::ILLEGAL_PARAMETER
Definition: tls_magic.h:75
Botan::TLS_Client::read
size_t read(byte buf[], size_t buf_len)
Definition: tls_client.cpp:182
Botan::DECRYPT_ERROR
Definition: tls_magic.h:79
Botan::CLOSE_NOTIFY
Definition: tls_magic.h:63
Botan::Record_Reader::set_keys
void set_keys(const CipherSuite &suite, const SessionKeys &keys, Connection_Side side)
Definition: rec_read.cpp:46
Botan::TLS_ALGO_SIGNER_ANON
Definition: tls_magic.h:147
Botan
Definition: algo_base.h:14
Botan::Record_Writer::flush
void flush()
Definition: rec_wri.cpp:162
Botan::SecureQueue::write
void write(const byte[], size_t)
Definition: secqueue.cpp:117
Botan::HELLO_REQUEST
Definition: tls_magic.h:41
Botan::TLS_ALGO_KEYEXCH_DH
Definition: tls_magic.h:155
Botan::Alert_Type
Alert_Type
Definition: tls_magic.h:62
Botan::HANDSHAKE_CCS
Definition: tls_magic.h:53
Botan::CERTIFICATE
Definition: tls_magic.h:45
Botan::SERVER_HELLO_DONE
Definition: tls_magic.h:48
Botan::TLS_Client::close
void close()
Definition: tls_client.cpp:204
Botan::APPLICATION_DATA
Definition: tls_magic.h:37
Botan::CONNECTION_CLOSED
Definition: tls_magic.h:32
Botan::INTERNAL_ERROR
Definition: tls_magic.h:83
Botan::TLS_Policy
Definition: tls_policy.h:22
Botan::Record_Writer::alert
void alert(Alert_Level, Alert_Type)
Definition: rec_wri.cpp:264
Botan::make_u32bit
u32bit make_u32bit(byte i0, byte i1, byte i2, byte i3)
Definition: loadstor.h:60
Botan::TLS_ALGO_SIGNER_RSA
Definition: tls_magic.h:148
Botan::FATAL
Definition: tls_magic.h:59
Botan::TLS_Client::write
void write(const byte buf[], size_t buf_len)
Definition: tls_client.cpp:170
Botan::TLS_Client::~TLS_Client
~TLS_Client()
Definition: tls_client.cpp:105
Botan::CHANGE_CIPHER_SPEC
Definition: tls_magic.h:34
Botan::TLS_ALGO_KEYEXCH_RSA
Definition: tls_magic.h:154
Botan::HANDSHAKE_NONE
Definition: tls_magic.h:54
Botan::BAD_CERTIFICATE
Definition: tls_magic.h:70
Botan::SERVER_HELLO
Definition: tls_magic.h:44
Botan::Record_Writer::reset
void reset()
Definition: rec_wri.cpp:30
Botan::CLIENT
Definition: tls_magic.h:29
Botan::Record_Writer::send
void send(byte type, const byte input[], size_t length)
Definition: rec_wri.cpp:131