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
16namespace Botan {
17
18namespace {
19
20/**
21* Verify the state transition is allowed
22* FIXME: checks are wrong for session reuse (add a flag for that)
23*/
24void 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*/
84TLS_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,
88 input_fn(input_fn),
89 policy(policy),
90 rng(rng),
91 writer(output_fn)
92 {
93 initialize();
94 }
95
97 Private_Key* cert_key)
98 {
99 certs.push_back(std::make_pair(cert, cert_key));
100 }
101
102/**
103* TLS Client Destructor
104*/
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*/
116void 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*/
162std::vector<X509_Certificate> TLS_Client::peer_cert_chain() const
163 {
164 return peer_certs;
165 }
166
167/**
168* Write to a TLS connection
169*/
170void TLS_Client::write(const byte buf[], size_t length)
171 {
172 if(!active)
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*/
182size_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*/
205 {
207 }
208
209/**
210* Check connection status
211*/
213 {
214 if(!active)
215 return true;
216 return false;
217 }
218
219/**
220* Close a TLS connection
221*/
222void 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*/
239void 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*/
303void 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 {
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*/
360void 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 )
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())
395 "TLS_Client: Server replied with bad version");
396
397 if(state->version < policy.min_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)
418 "TLS_Client: No certificates sent by server");
419
420 if(!policy.check_cert(peer_certs))
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
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))
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
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))
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()))
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))
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*/
560void 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}
Certificate_Req(Record_Writer &, HandshakeHash &, const std::vector< X509_Certificate > &)
Definition cert_req.cpp:20
Certificate_Verify(RandomNumberGenerator &rng, Record_Writer &, HandshakeHash &, const Private_Key *)
Definition cert_ver.cpp:21
Certificate(Record_Writer &, const std::vector< X509_Certificate > &, HandshakeHash &)
Definition cert_req.cpp:86
Client_Hello(RandomNumberGenerator &rng, Record_Writer &, const TLS_Policy &, HandshakeHash &)
Definition hello.cpp:65
Client_Key_Exchange(RandomNumberGenerator &rng, Record_Writer &output, HandshakeHash &hash, const Public_Key *my_key, Version_Code using_version, Version_Code pref_version)
Definition c_kex.cpp:22
Finished(Record_Writer &, Version_Code, Connection_Side, const MemoryRegion< byte > &, HandshakeHash &)
Definition finished.cpp:16
void alert(Alert_Level, Alert_Type)
Definition rec_wri.cpp:264
void set_version(Version_Code)
Definition rec_wri.cpp:51
Server_Hello_Done(Record_Writer &, HandshakeHash &)
Definition hello.cpp:308
Server_Hello(RandomNumberGenerator &rng, Record_Writer &, const TLS_Policy &, const std::vector< X509_Certificate > &, const Client_Hello &, Version_Code, HandshakeHash &)
Definition hello.cpp:223
Server_Key_Exchange(RandomNumberGenerator &rng, Record_Writer &, const Public_Key *, const Private_Key *, const MemoryRegion< byte > &, const MemoryRegion< byte > &, HandshakeHash &)
Definition s_kex.cpp:22
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)
std::vector< X509_Certificate > peer_cert_chain() const
bool is_closed() const
size_t read(byte buf[], size_t buf_len)
void write(const byte buf[], size_t buf_len)
void add_client_cert(const X509_Certificate &cert, Private_Key *cert_key)
TLS_Exception(Alert_Type type, const std::string &err_msg="Unknown error")
Definition tls_exceptn.h:24
virtual Version_Code pref_version() const
Definition tls_policy.h:50
Alert_Type
Definition tls_magic.h:62
@ PROTOCOL_VERSION
Definition tls_magic.h:81
@ HANDSHAKE_FAILURE
Definition tls_magic.h:69
@ INTERNAL_ERROR
Definition tls_magic.h:83
@ BAD_CERTIFICATE
Definition tls_magic.h:70
@ DECRYPT_ERROR
Definition tls_magic.h:79
@ CLOSE_NOTIFY
Definition tls_magic.h:63
@ NO_ALERT_TYPE
Definition tls_magic.h:89
@ ILLEGAL_PARAMETER
Definition tls_magic.h:75
@ UNSUPPORTED_CERTIFICATE
Definition tls_magic.h:71
byte get_byte(size_t byte_num, T input)
Definition get_byte.h:21
@ SERVER
Definition tls_magic.h:29
@ CLIENT
Definition tls_magic.h:29
u32bit make_u32bit(byte i0, byte i1, byte i2, byte i3)
Definition loadstor.h:60
@ TLS_ALGO_KEYEXCH_DH
Definition tls_magic.h:155
@ TLS_ALGO_SIGNER_ANON
Definition tls_magic.h:147
@ TLS_ALGO_KEYEXCH_NOKEX
Definition tls_magic.h:153
@ TLS_ALGO_SIGNER_RSA
Definition tls_magic.h:148
@ TLS_ALGO_KEYEXCH_RSA
Definition tls_magic.h:154
@ TLS_ALGO_SIGNER_DSA
Definition tls_magic.h:149
@ ALERT
Definition tls_magic.h:35
@ APPLICATION_DATA
Definition tls_magic.h:37
@ HANDSHAKE
Definition tls_magic.h:36
@ CONNECTION_CLOSED
Definition tls_magic.h:32
@ CHANGE_CIPHER_SPEC
Definition tls_magic.h:34
Handshake_Type
Definition tls_magic.h:40
@ HELLO_REQUEST
Definition tls_magic.h:41
@ SERVER_HELLO
Definition tls_magic.h:44
@ FINISHED
Definition tls_magic.h:51
@ HANDSHAKE_NONE
Definition tls_magic.h:54
@ HANDSHAKE_CCS
Definition tls_magic.h:53
@ CERTIFICATE
Definition tls_magic.h:45
@ CERTIFICATE_REQUEST
Definition tls_magic.h:47
@ SERVER_KEX
Definition tls_magic.h:46
@ SERVER_HELLO_DONE
Definition tls_magic.h:48
Alert_Level
Definition tls_magic.h:57
@ WARNING
Definition tls_magic.h:58
@ FATAL
Definition tls_magic.h:59
Decoding_Error(const std::string &name)
Definition exceptn.h:140
Stream_IO_Error(const std::string &err)
Definition exceptn.h:167
Unexpected_Message(const std::string &err)
Definition tls_exceptn.h:37