]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libtls/tls_peer.c
Support different hash/sig algorithms in handshake signing, including ECDSA
[thirdparty/strongswan.git] / src / libtls / tls_peer.c
CommitLineData
4c0c2283
MW
1/*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16#include "tls_peer.h"
17
0f82a470 18#include <debug.h>
c8114799 19#include <credentials/certificates/x509.h>
4c0c2283
MW
20
21#include <time.h>
22
23typedef struct private_tls_peer_t private_tls_peer_t;
24
698674c7
MW
25typedef enum {
26 STATE_INIT,
27 STATE_HELLO_SENT,
8fef06a6 28 STATE_HELLO_RECEIVED,
3e962b08 29 STATE_HELLO_DONE,
3ddd164e 30 STATE_CERT_SENT,
8fef06a6
MW
31 STATE_CERT_RECEIVED,
32 STATE_CERTREQ_RECEIVED,
3ddd164e
MW
33 STATE_KEY_EXCHANGE_SENT,
34 STATE_VERIFY_SENT,
f139b578 35 STATE_CIPHERSPEC_CHANGED_OUT,
3ddd164e 36 STATE_FINISHED_SENT,
f139b578 37 STATE_CIPHERSPEC_CHANGED_IN,
110364b0 38 STATE_COMPLETE,
698674c7
MW
39} peer_state_t;
40
4c0c2283
MW
41/**
42 * Private data of an tls_peer_t object.
43 */
44struct private_tls_peer_t {
45
46 /**
47 * Public tls_peer_t interface.
48 */
49 tls_peer_t public;
536dbc00 50
3e962b08
MW
51 /**
52 * TLS stack
53 */
54 tls_t *tls;
55
536dbc00
MW
56 /**
57 * TLS crypto context
58 */
59 tls_crypto_t *crypto;
698674c7 60
e6f3ef13
MW
61 /**
62 * TLS alert handler
63 */
64 tls_alert_t *alert;
65
3ddd164e 66 /**
69e8bb2e 67 * Peer identity, NULL for no client authentication
3ddd164e
MW
68 */
69 identification_t *peer;
70
71 /**
72 * Server identity
73 */
74 identification_t *server;
75
698674c7
MW
76 /**
77 * State we are in
78 */
79 peer_state_t state;
3ddd164e 80
18010de2
MW
81 /**
82 * Hello random data selected by client
83 */
84 char client_random[32];
85
86 /**
87 * Hello random data selected by server
88 */
89 char server_random[32];
90
3ddd164e
MW
91 /**
92 * Auth helper for peer authentication
93 */
94 auth_cfg_t *peer_auth;
95
96 /**
97 * Auth helper for server authentication
98 */
99 auth_cfg_t *server_auth;
100
101 /**
102 * Peer private key
103 */
104 private_key_t *private;
dbb7c030
MW
105
106 /**
107 * List of server-supported hashsig algorithms
108 */
109 chunk_t hashsig;
110
111 /**
112 * List of server-supported client certificate types
113 */
114 chunk_t cert_types;
4c0c2283
MW
115};
116
3e962b08
MW
117/**
118 * Process a server hello message
119 */
4ef946dd
MW
120static status_t process_server_hello(private_tls_peer_t *this,
121 tls_reader_t *reader)
3e962b08 122{
4ef946dd
MW
123 u_int8_t compression;
124 u_int16_t version, cipher;
4ef946dd 125 chunk_t random, session, ext = chunk_empty;
18010de2 126 tls_cipher_suite_t suite;
4ef946dd 127
84d67ead
MW
128 this->crypto->append_handshake(this->crypto,
129 TLS_SERVER_HELLO, reader->peek(reader));
3ddd164e 130
4ef946dd 131 if (!reader->read_uint16(reader, &version) ||
18010de2 132 !reader->read_data(reader, sizeof(this->server_random), &random) ||
4ef946dd
MW
133 !reader->read_data8(reader, &session) ||
134 !reader->read_uint16(reader, &cipher) ||
135 !reader->read_uint8(reader, &compression) ||
136 (reader->remaining(reader) && !reader->read_data16(reader, &ext)))
3e962b08 137 {
3c19b346 138 DBG1(DBG_TLS, "received invalid ServerHello");
e6f3ef13
MW
139 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
140 return NEED_MORE;
4ef946dd 141 }
18010de2
MW
142
143 memcpy(this->server_random, random.ptr, sizeof(this->server_random));
144
f154e304 145 if (!this->tls->set_version(this->tls, version))
4ef946dd 146 {
f154e304
MW
147 DBG1(DBG_TLS, "negotiated version %N not supported",
148 tls_version_names, version);
e6f3ef13
MW
149 this->alert->add(this->alert, TLS_FATAL, TLS_PROTOCOL_VERSION);
150 return NEED_MORE;
3e962b08 151 }
18010de2
MW
152 suite = cipher;
153 if (!this->crypto->select_cipher_suite(this->crypto, &suite, 1))
154 {
3c19b346 155 DBG1(DBG_TLS, "received TLS cipher suite %N inacceptable",
0bcef5fe 156 tls_cipher_suite_names, suite);
e6f3ef13
MW
157 this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
158 return NEED_MORE;
18010de2 159 }
3c19b346 160 DBG1(DBG_TLS, "negotiated TLS version %N with suite %N",
0bcef5fe 161 tls_version_names, version, tls_cipher_suite_names, suite);
8fef06a6 162 this->state = STATE_HELLO_RECEIVED;
4ef946dd 163 return NEED_MORE;
3e962b08
MW
164}
165
c8114799
MW
166/**
167 * Check if a server certificate is acceptable for the given server identity
168 */
169static bool check_certificate(private_tls_peer_t *this, certificate_t *cert)
170{
171 identification_t *id;
172
173 if (cert->has_subject(cert, this->server))
174 {
175 return TRUE;
176 }
177 id = cert->get_subject(cert);
178 if (id->matches(id, this->server))
179 {
180 return TRUE;
181 }
182 if (cert->get_type(cert) == CERT_X509)
183 {
184 x509_t *x509 = (x509_t*)cert;
185 enumerator_t *enumerator;
186
187 enumerator = x509->create_subjectAltName_enumerator(x509);
188 while (enumerator->enumerate(enumerator, &id))
189 {
190 if (id->matches(id, this->server))
191 {
192 enumerator->destroy(enumerator);
193 return TRUE;
194 }
195 }
196 enumerator->destroy(enumerator);
197 }
198 DBG1(DBG_TLS, "server certificate does not match to '%Y'", this->server);
199 return FALSE;
200}
201
3e962b08
MW
202/**
203 * Process a Certificate message
204 */
4ef946dd
MW
205static status_t process_certificate(private_tls_peer_t *this,
206 tls_reader_t *reader)
3e962b08 207{
4ef946dd
MW
208 certificate_t *cert;
209 tls_reader_t *certs;
210 chunk_t data;
3ddd164e
MW
211 bool first = TRUE;
212
84d67ead
MW
213 this->crypto->append_handshake(this->crypto,
214 TLS_CERTIFICATE, reader->peek(reader));
3e962b08 215
4ef946dd
MW
216 if (!reader->read_data24(reader, &data))
217 {
e6f3ef13
MW
218 DBG1(DBG_TLS, "certificate message header invalid");
219 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
220 return NEED_MORE;
4ef946dd
MW
221 }
222 certs = tls_reader_create(data);
223 while (certs->remaining(certs))
224 {
225 if (!certs->read_data24(certs, &data))
3e962b08 226 {
e6f3ef13
MW
227 DBG1(DBG_TLS, "certificate message invalid");
228 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
4ef946dd 229 certs->destroy(certs);
e6f3ef13 230 return NEED_MORE;
3e962b08 231 }
4ef946dd 232 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
3ddd164e 233 BUILD_BLOB_ASN1_DER, data, BUILD_END);
4ef946dd 234 if (cert)
3e962b08 235 {
3ddd164e
MW
236 if (first)
237 {
c8114799
MW
238 if (!check_certificate(this, cert))
239 {
240 cert->destroy(cert);
241 certs->destroy(certs);
242 this->alert->add(this->alert, TLS_FATAL, TLS_ACCESS_DENIED);
243 return NEED_MORE;
244 }
3ddd164e 245 this->server_auth->add(this->server_auth,
400df4ca 246 AUTH_HELPER_SUBJECT_CERT, cert);
3c19b346 247 DBG1(DBG_TLS, "received TLS server certificate '%Y'",
3ddd164e
MW
248 cert->get_subject(cert));
249 first = FALSE;
250 }
251 else
252 {
3c19b346 253 DBG1(DBG_TLS, "received TLS intermediate certificate '%Y'",
3ddd164e
MW
254 cert->get_subject(cert));
255 this->server_auth->add(this->server_auth,
400df4ca 256 AUTH_HELPER_IM_CERT, cert);
3ddd164e
MW
257 }
258 }
259 else
260 {
3c19b346 261 DBG1(DBG_TLS, "parsing TLS certificate failed, skipped");
e6f3ef13 262 this->alert->add(this->alert, TLS_WARNING, TLS_BAD_CERTIFICATE);
3e962b08
MW
263 }
264 }
4ef946dd 265 certs->destroy(certs);
8fef06a6 266 this->state = STATE_CERT_RECEIVED;
3e962b08
MW
267 return NEED_MORE;
268}
269
270/**
69e8bb2e 271 * Process a Certificate Request message
3e962b08 272 */
4ef946dd 273static status_t process_certreq(private_tls_peer_t *this, tls_reader_t *reader)
3e962b08 274{
4ef946dd
MW
275 chunk_t types, hashsig, data;
276 tls_reader_t *authorities;
3e962b08 277 identification_t *id;
3ddd164e
MW
278 certificate_t *cert;
279
69e8bb2e
MW
280 if (!this->peer)
281 {
282 DBG1(DBG_TLS, "server requested a certificate, but client "
283 "authentication disabled");
284 this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
285 return NEED_MORE;
286 }
84d67ead
MW
287 this->crypto->append_handshake(this->crypto,
288 TLS_CERTIFICATE_REQUEST, reader->peek(reader));
3e962b08 289
4ef946dd 290 if (!reader->read_data8(reader, &types))
3e962b08 291 {
e6f3ef13
MW
292 DBG1(DBG_TLS, "certreq message header invalid");
293 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
294 return NEED_MORE;
3e962b08 295 }
dbb7c030 296 this->cert_types = chunk_clone(types);
3e962b08
MW
297 if (this->tls->get_version(this->tls) >= TLS_1_2)
298 {
4ef946dd 299 if (!reader->read_data16(reader, &hashsig))
3e962b08 300 {
e6f3ef13
MW
301 DBG1(DBG_TLS, "certreq message invalid");
302 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
303 return NEED_MORE;
3e962b08 304 }
dbb7c030 305 this->hashsig = chunk_clone(hashsig);
3e962b08 306 }
4ef946dd 307 if (!reader->read_data16(reader, &data))
3e962b08 308 {
e6f3ef13
MW
309 DBG1(DBG_TLS, "certreq message invalid");
310 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
311 return NEED_MORE;
3e962b08 312 }
4ef946dd
MW
313 authorities = tls_reader_create(data);
314 while (authorities->remaining(authorities))
3e962b08 315 {
4ef946dd 316 if (!authorities->read_data16(authorities, &data))
3e962b08 317 {
e6f3ef13
MW
318 DBG1(DBG_TLS, "certreq message invalid");
319 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
4ef946dd 320 authorities->destroy(authorities);
e6f3ef13 321 return NEED_MORE;
3e962b08 322 }
4ef946dd 323 id = identification_create_from_encoding(ID_DER_ASN1_DN, data);
0b71bc7a
MW
324 cert = lib->credmgr->get_cert(lib->credmgr,
325 CERT_X509, KEY_ANY, id, TRUE);
3ddd164e
MW
326 if (cert)
327 {
3c19b346 328 DBG1(DBG_TLS, "received TLS cert request for '%Y", id);
3ddd164e
MW
329 this->peer_auth->add(this->peer_auth, AUTH_RULE_CA_CERT, cert);
330 }
331 else
332 {
3c19b346 333 DBG1(DBG_TLS, "received TLS cert request for unknown CA '%Y'", id);
3ddd164e 334 }
3e962b08 335 id->destroy(id);
3e962b08 336 }
4ef946dd 337 authorities->destroy(authorities);
8fef06a6 338 this->state = STATE_CERTREQ_RECEIVED;
3e962b08
MW
339 return NEED_MORE;
340}
341
3ddd164e
MW
342/**
343 * Process Hello Done message
344 */
345static status_t process_hello_done(private_tls_peer_t *this,
346 tls_reader_t *reader)
347{
84d67ead
MW
348 this->crypto->append_handshake(this->crypto,
349 TLS_SERVER_HELLO_DONE, reader->peek(reader));
3ddd164e
MW
350 this->state = STATE_HELLO_DONE;
351 return NEED_MORE;
352}
353
f139b578
MW
354/**
355 * Process finished message
356 */
357static status_t process_finished(private_tls_peer_t *this, tls_reader_t *reader)
358{
84d67ead
MW
359 chunk_t received;
360 char buf[12];
110364b0 361
84d67ead 362 if (!reader->read_data(reader, sizeof(buf), &received))
110364b0 363 {
3c19b346 364 DBG1(DBG_TLS, "received server finished too short");
e6f3ef13
MW
365 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
366 return NEED_MORE;
110364b0 367 }
84d67ead 368 if (!this->crypto->calculate_finished(this->crypto, "server finished", buf))
110364b0 369 {
3c19b346 370 DBG1(DBG_TLS, "calculating server finished failed");
e6f3ef13
MW
371 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
372 return NEED_MORE;
110364b0 373 }
84d67ead 374 if (!chunk_equals(received, chunk_from_thing(buf)))
110364b0 375 {
3c19b346 376 DBG1(DBG_TLS, "received server finished invalid");
e6f3ef13
MW
377 this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
378 return NEED_MORE;
110364b0
MW
379 }
380 this->state = STATE_COMPLETE;
84d67ead
MW
381 this->crypto->derive_eap_msk(this->crypto,
382 chunk_from_thing(this->client_random),
383 chunk_from_thing(this->server_random));
110364b0 384 return NEED_MORE;
f139b578
MW
385}
386
4c0c2283 387METHOD(tls_handshake_t, process, status_t,
4ef946dd 388 private_tls_peer_t *this, tls_handshake_type_t type, tls_reader_t *reader)
4c0c2283 389{
8fef06a6
MW
390 tls_handshake_type_t expected;
391
3e962b08
MW
392 switch (this->state)
393 {
394 case STATE_HELLO_SENT:
8fef06a6
MW
395 if (type == TLS_SERVER_HELLO)
396 {
397 return process_server_hello(this, reader);
398 }
399 expected = TLS_SERVER_HELLO;
400 break;
401 case STATE_HELLO_RECEIVED:
402 if (type == TLS_CERTIFICATE)
3e962b08 403 {
8fef06a6 404 return process_certificate(this, reader);
3e962b08 405 }
8fef06a6
MW
406 expected = TLS_CERTIFICATE;
407 break;
408 case STATE_CERT_RECEIVED:
409 if (type == TLS_CERTIFICATE_REQUEST)
410 {
411 return process_certreq(this, reader);
412 }
69e8bb2e 413 this->peer = NULL;
b4d30a42 414 /* fall through since TLS_CERTIFICATE_REQUEST is optional */
8fef06a6
MW
415 case STATE_CERTREQ_RECEIVED:
416 if (type == TLS_SERVER_HELLO_DONE)
417 {
418 return process_hello_done(this, reader);
419 }
420 expected = TLS_SERVER_HELLO_DONE;
3e962b08 421 break;
f139b578 422 case STATE_CIPHERSPEC_CHANGED_IN:
8fef06a6 423 if (type == TLS_FINISHED)
f139b578 424 {
8fef06a6 425 return process_finished(this, reader);
f139b578 426 }
8fef06a6 427 expected = TLS_FINISHED;
f139b578 428 break;
3e962b08 429 default:
3c19b346 430 DBG1(DBG_TLS, "TLS %N not expected in current state",
8fef06a6 431 tls_handshake_type_names, type);
e6f3ef13
MW
432 this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE);
433 return NEED_MORE;
3e962b08 434 }
3c19b346 435 DBG1(DBG_TLS, "TLS %N expected, but received %N",
8fef06a6 436 tls_handshake_type_names, expected, tls_handshake_type_names, type);
e6f3ef13
MW
437 this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE);
438 return NEED_MORE;
4c0c2283
MW
439}
440
698674c7
MW
441/**
442 * Send a client hello
443 */
8fef06a6
MW
444static status_t send_client_hello(private_tls_peer_t *this,
445 tls_handshake_type_t *type, tls_writer_t *writer)
698674c7 446{
7ea87db0
AS
447 tls_cipher_suite_t *suites;
448 tls_version_t version;
3a1640de 449 int count, i;
698674c7
MW
450 rng_t *rng;
451
18010de2 452 htoun32(&this->client_random, time(NULL));
698674c7
MW
453 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
454 if (!rng)
455 {
e6f3ef13
MW
456 DBG1(DBG_TLS, "no suitable RNG found to generate client random");
457 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
458 return NEED_MORE;
698674c7 459 }
18010de2 460 rng->get_bytes(rng, sizeof(this->client_random) - 4, this->client_random + 4);
3a1640de
MW
461 rng->destroy(rng);
462
7ea87db0
AS
463 /* TLS version */
464 version = this->tls->get_version(this->tls);
7ea87db0 465 writer->write_uint16(writer, version);
18010de2 466 writer->write_data(writer, chunk_from_thing(this->client_random));
7ea87db0 467
3a1640de
MW
468 /* session identifier => none */
469 writer->write_data8(writer, chunk_empty);
470
7ea87db0
AS
471 /* add TLS cipher suites */
472 count = this->crypto->get_cipher_suites(this->crypto, &suites);
3a1640de
MW
473 writer->write_uint16(writer, count * 2);
474 for (i = 0; i < count; i++)
475 {
7ea87db0 476 writer->write_uint16(writer, suites[i]);
3a1640de 477 }
7ea87db0 478
3a1640de
MW
479 /* NULL compression only */
480 writer->write_uint8(writer, 1);
481 writer->write_uint8(writer, 0);
482
483 *type = TLS_CLIENT_HELLO;
3e962b08 484 this->state = STATE_HELLO_SENT;
84d67ead 485 this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
3ddd164e
MW
486 return NEED_MORE;
487}
488
dbb7c030
MW
489/**
490 * Find a private key suitable to sign Certificate Verify
491 */
492static private_key_t *find_private_key(private_tls_peer_t *this)
493{
494 private_key_t *key = NULL;
495 tls_reader_t *reader;
496 key_type_t type;
497 u_int8_t cert;
498
499 if (!this->peer)
500 {
501 return NULL;
502 }
503 reader = tls_reader_create(this->cert_types);
504 while (reader->remaining(reader) && reader->read_uint8(reader, &cert))
505 {
506 switch (cert)
507 {
508 case TLS_RSA_SIGN:
509 type = KEY_RSA;
510 break;
511 case TLS_ECDSA_SIGN:
512 type = KEY_ECDSA;
513 break;
514 default:
515 continue;
516 }
517 key = lib->credmgr->get_private(lib->credmgr, type,
518 this->peer, this->peer_auth);
519 if (key)
520 {
521 break;
522 }
523 }
524 reader->destroy(reader);
525 return key;
526}
527
3ddd164e
MW
528/**
529 * Send Certificate
530 */
531static status_t send_certificate(private_tls_peer_t *this,
532 tls_handshake_type_t *type, tls_writer_t *writer)
533{
534 enumerator_t *enumerator;
535 certificate_t *cert;
536 auth_rule_t rule;
537 tls_writer_t *certs;
538 chunk_t data;
539
dbb7c030 540 this->private = find_private_key(this);
3ddd164e
MW
541 if (!this->private)
542 {
3c19b346 543 DBG1(DBG_TLS, "no TLS peer certificate found for '%Y'", this->peer);
a596006e 544 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
69e8bb2e 545 return FAILED;
3ddd164e
MW
546 }
547
548 /* generate certificate payload */
549 certs = tls_writer_create(256);
550 cert = this->peer_auth->get(this->peer_auth, AUTH_RULE_SUBJECT_CERT);
551 if (cert)
552 {
0b71bc7a
MW
553 if (cert->get_encoding(cert, CERT_ASN1_DER, &data))
554 {
3c19b346 555 DBG1(DBG_TLS, "sending TLS peer certificate '%Y'",
0b71bc7a
MW
556 cert->get_subject(cert));
557 certs->write_data24(certs, data);
558 free(data.ptr);
559 }
3ddd164e
MW
560 }
561 enumerator = this->peer_auth->create_enumerator(this->peer_auth);
562 while (enumerator->enumerate(enumerator, &rule, &cert))
563 {
564 if (rule == AUTH_RULE_IM_CERT)
565 {
0b71bc7a
MW
566 if (cert->get_encoding(cert, CERT_ASN1_DER, &data))
567 {
3c19b346 568 DBG1(DBG_TLS, "sending TLS intermediate certificate '%Y'",
0b71bc7a
MW
569 cert->get_subject(cert));
570 certs->write_data24(certs, data);
571 free(data.ptr);
572 }
3ddd164e
MW
573 }
574 }
575 enumerator->destroy(enumerator);
576
577 writer->write_data24(writer, certs->get_buf(certs));
578 certs->destroy(certs);
579
580 *type = TLS_CERTIFICATE;
581 this->state = STATE_CERT_SENT;
84d67ead 582 this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
3ddd164e
MW
583 return NEED_MORE;
584}
585
586/**
587 * Send client key exchange
588 */
589static status_t send_key_exchange(private_tls_peer_t *this,
590 tls_handshake_type_t *type, tls_writer_t *writer)
591{
592 public_key_t *public = NULL, *current;
e85bca7f 593 certificate_t *cert;
3ddd164e
MW
594 enumerator_t *enumerator;
595 auth_cfg_t *auth;
596 rng_t *rng;
597 char premaster[48];
598 chunk_t encrypted;
599
600 rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
601 if (!rng)
602 {
3c19b346 603 DBG1(DBG_TLS, "no suitable RNG found for TLS premaster secret");
a596006e 604 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
3ddd164e
MW
605 return FAILED;
606 }
607 rng->get_bytes(rng, sizeof(premaster) - 2, premaster + 2);
608 rng->destroy(rng);
609 htoun16(premaster, TLS_1_2);
610
84d67ead
MW
611 this->crypto->derive_secrets(this->crypto, chunk_from_thing(premaster),
612 chunk_from_thing(this->client_random),
613 chunk_from_thing(this->server_random));
18010de2 614
e85bca7f
MW
615 cert = this->server_auth->get(this->server_auth, AUTH_HELPER_SUBJECT_CERT);
616 if (cert)
3ddd164e 617 {
e85bca7f
MW
618 enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
619 KEY_ANY, cert->get_subject(cert), this->server_auth);
620 while (enumerator->enumerate(enumerator, &current, &auth))
621 {
622 public = current->get_ref(current);
623 break;
624 }
625 enumerator->destroy(enumerator);
3ddd164e 626 }
3ddd164e
MW
627 if (!public)
628 {
3c19b346 629 DBG1(DBG_TLS, "no TLS public key found for server '%Y'", this->server);
a596006e 630 this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN);
3ddd164e
MW
631 return FAILED;
632 }
33ddaaab
MW
633 if (!public->encrypt(public, ENCRYPT_RSA_PKCS1,
634 chunk_from_thing(premaster), &encrypted))
3ddd164e
MW
635 {
636 public->destroy(public);
3c19b346 637 DBG1(DBG_TLS, "encrypting TLS premaster secret failed");
a596006e 638 this->alert->add(this->alert, TLS_FATAL, TLS_BAD_CERTIFICATE);
3ddd164e
MW
639 return FAILED;
640 }
400df4ca 641
3ddd164e
MW
642 public->destroy(public);
643
644 writer->write_data16(writer, encrypted);
645 free(encrypted.ptr);
646
647 *type = TLS_CLIENT_KEY_EXCHANGE;
648 this->state = STATE_KEY_EXCHANGE_SENT;
84d67ead 649 this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
3ddd164e
MW
650 return NEED_MORE;
651}
652
653/**
654 * Send certificate verify
655 */
656static status_t send_certificate_verify(private_tls_peer_t *this,
657 tls_handshake_type_t *type, tls_writer_t *writer)
658{
84d67ead 659 if (!this->private ||
dbb7c030
MW
660 !this->crypto->sign_handshake(this->crypto, this->private,
661 writer, this->hashsig))
3ddd164e 662 {
3c19b346 663 DBG1(DBG_TLS, "creating TLS Certificate Verify signature failed");
a596006e 664 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
3ddd164e
MW
665 return FAILED;
666 }
3ddd164e
MW
667
668 *type = TLS_CERTIFICATE_VERIFY;
669 this->state = STATE_VERIFY_SENT;
84d67ead 670 this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
3ddd164e
MW
671 return NEED_MORE;
672}
673
674/**
675 * Send Finished
676 */
677static status_t send_finished(private_tls_peer_t *this,
678 tls_handshake_type_t *type, tls_writer_t *writer)
679{
84d67ead 680 char buf[12];
18010de2 681
84d67ead 682 if (!this->crypto->calculate_finished(this->crypto, "client finished", buf))
18010de2 683 {
3c19b346 684 DBG1(DBG_TLS, "calculating client finished data failed");
a596006e 685 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
18010de2
MW
686 return FAILED;
687 }
18010de2 688
84d67ead 689 writer->write_data(writer, chunk_from_thing(buf));
18010de2 690
3ddd164e
MW
691 *type = TLS_FINISHED;
692 this->state = STATE_FINISHED_SENT;
84d67ead 693 this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
698674c7
MW
694 return NEED_MORE;
695}
696
4c0c2283 697METHOD(tls_handshake_t, build, status_t,
3a1640de 698 private_tls_peer_t *this, tls_handshake_type_t *type, tls_writer_t *writer)
4c0c2283 699{
698674c7
MW
700 switch (this->state)
701 {
702 case STATE_INIT:
8fef06a6 703 return send_client_hello(this, type, writer);
3ddd164e 704 case STATE_HELLO_DONE:
69e8bb2e 705 if (this->peer)
b4d30a42
AS
706 {
707 return send_certificate(this, type, writer);
708 }
709 /* otherwise fall through to next state */
3ddd164e
MW
710 case STATE_CERT_SENT:
711 return send_key_exchange(this, type, writer);
712 case STATE_KEY_EXCHANGE_SENT:
69e8bb2e 713 if (this->peer)
b4d30a42
AS
714 {
715 return send_certificate_verify(this, type, writer);
716 }
717 else
718 {
719 return INVALID_STATE;
720 }
f139b578 721 case STATE_CIPHERSPEC_CHANGED_OUT:
3ddd164e 722 return send_finished(this, type, writer);
698674c7
MW
723 default:
724 return INVALID_STATE;
725 }
4c0c2283
MW
726}
727
3ddd164e
MW
728METHOD(tls_handshake_t, cipherspec_changed, bool,
729 private_tls_peer_t *this)
730{
69e8bb2e
MW
731 if ((this->peer && this->state == STATE_VERIFY_SENT) ||
732 (!this->peer && this->state == STATE_KEY_EXCHANGE_SENT))
3ddd164e 733 {
84543e6e 734 this->crypto->change_cipher(this->crypto, FALSE);
f139b578 735 this->state = STATE_CIPHERSPEC_CHANGED_OUT;
3ddd164e
MW
736 return TRUE;
737 }
738 return FALSE;
739}
740
f139b578 741METHOD(tls_handshake_t, change_cipherspec, bool,
3ddd164e
MW
742 private_tls_peer_t *this)
743{
f139b578
MW
744 if (this->state == STATE_FINISHED_SENT)
745 {
746 this->crypto->change_cipher(this->crypto, TRUE);
747 this->state = STATE_CIPHERSPEC_CHANGED_IN;
748 return TRUE;
749 }
750 return FALSE;
3ddd164e
MW
751}
752
1327839d
AS
753METHOD(tls_handshake_t, finished, bool,
754 private_tls_peer_t *this)
755{
756 return this->state == STATE_COMPLETE;
757}
758
4c0c2283
MW
759METHOD(tls_handshake_t, destroy, void,
760 private_tls_peer_t *this)
761{
3ddd164e 762 DESTROY_IF(this->private);
3ddd164e
MW
763 this->peer_auth->destroy(this->peer_auth);
764 this->server_auth->destroy(this->server_auth);
dbb7c030
MW
765 free(this->hashsig.ptr);
766 free(this->cert_types.ptr);
4c0c2283
MW
767 free(this);
768}
769
770/**
771 * See header
772 */
e6f3ef13 773tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert,
3ddd164e 774 identification_t *peer, identification_t *server)
4c0c2283
MW
775{
776 private_tls_peer_t *this;
777
778 INIT(this,
ba31fe1f
MW
779 .public = {
780 .handshake = {
781 .process = _process,
782 .build = _build,
783 .cipherspec_changed = _cipherspec_changed,
784 .change_cipherspec = _change_cipherspec,
785 .finished = _finished,
786 .destroy = _destroy,
787 },
4c0c2283 788 },
698674c7 789 .state = STATE_INIT,
3e962b08 790 .tls = tls,
536dbc00 791 .crypto = crypto,
e6f3ef13 792 .alert = alert,
3ddd164e
MW
793 .peer = peer,
794 .server = server,
795 .peer_auth = auth_cfg_create(),
796 .server_auth = auth_cfg_create(),
4c0c2283
MW
797 );
798
799 return &this->public;
800}