]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libtls/tls_peer.c
diffie-hellman: Add a bool return value to set_other_public_value()
[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
f05b4272 18#include <utils/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 31 STATE_CERT_RECEIVED,
da3f4a9f 32 STATE_KEY_EXCHANGE_RECEIVED,
8fef06a6 33 STATE_CERTREQ_RECEIVED,
3ddd164e
MW
34 STATE_KEY_EXCHANGE_SENT,
35 STATE_VERIFY_SENT,
f139b578 36 STATE_CIPHERSPEC_CHANGED_OUT,
3ddd164e 37 STATE_FINISHED_SENT,
f139b578 38 STATE_CIPHERSPEC_CHANGED_IN,
6a5c86b7 39 STATE_FINISHED_RECEIVED,
698674c7
MW
40} peer_state_t;
41
4c0c2283
MW
42/**
43 * Private data of an tls_peer_t object.
44 */
45struct private_tls_peer_t {
46
47 /**
48 * Public tls_peer_t interface.
49 */
50 tls_peer_t public;
536dbc00 51
3e962b08
MW
52 /**
53 * TLS stack
54 */
55 tls_t *tls;
56
536dbc00
MW
57 /**
58 * TLS crypto context
59 */
60 tls_crypto_t *crypto;
698674c7 61
e6f3ef13
MW
62 /**
63 * TLS alert handler
64 */
65 tls_alert_t *alert;
66
3ddd164e 67 /**
69e8bb2e 68 * Peer identity, NULL for no client authentication
3ddd164e
MW
69 */
70 identification_t *peer;
71
72 /**
73 * Server identity
74 */
75 identification_t *server;
76
698674c7
MW
77 /**
78 * State we are in
79 */
80 peer_state_t state;
3ddd164e 81
b37080f8
MW
82 /**
83 * TLS version we offered in hello
84 */
85 tls_version_t hello_version;
86
18010de2
MW
87 /**
88 * Hello random data selected by client
89 */
90 char client_random[32];
91
92 /**
93 * Hello random data selected by server
94 */
95 char server_random[32];
96
3ddd164e
MW
97 /**
98 * Auth helper for peer authentication
99 */
100 auth_cfg_t *peer_auth;
101
102 /**
103 * Auth helper for server authentication
104 */
105 auth_cfg_t *server_auth;
106
107 /**
108 * Peer private key
109 */
110 private_key_t *private;
dbb7c030 111
da3f4a9f
MW
112 /**
113 * DHE exchange
114 */
115 diffie_hellman_t *dh;
116
6a5c86b7
MW
117 /**
118 * Resuming a session?
119 */
120 bool resume;
121
122 /**
123 * TLS session identifier
124 */
125 chunk_t session;
126
dbb7c030
MW
127 /**
128 * List of server-supported hashsig algorithms
129 */
130 chunk_t hashsig;
131
132 /**
133 * List of server-supported client certificate types
134 */
135 chunk_t cert_types;
4c0c2283
MW
136};
137
3e962b08
MW
138/**
139 * Process a server hello message
140 */
4ef946dd 141static status_t process_server_hello(private_tls_peer_t *this,
7e432eff 142 bio_reader_t *reader)
3e962b08 143{
4ef946dd
MW
144 u_int8_t compression;
145 u_int16_t version, cipher;
4ef946dd 146 chunk_t random, session, ext = chunk_empty;
6a5c86b7 147 tls_cipher_suite_t suite = 0;
4ef946dd 148
84d67ead
MW
149 this->crypto->append_handshake(this->crypto,
150 TLS_SERVER_HELLO, reader->peek(reader));
3ddd164e 151
4ef946dd 152 if (!reader->read_uint16(reader, &version) ||
18010de2 153 !reader->read_data(reader, sizeof(this->server_random), &random) ||
4ef946dd
MW
154 !reader->read_data8(reader, &session) ||
155 !reader->read_uint16(reader, &cipher) ||
156 !reader->read_uint8(reader, &compression) ||
157 (reader->remaining(reader) && !reader->read_data16(reader, &ext)))
3e962b08 158 {
3c19b346 159 DBG1(DBG_TLS, "received invalid ServerHello");
e6f3ef13
MW
160 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
161 return NEED_MORE;
4ef946dd 162 }
18010de2
MW
163
164 memcpy(this->server_random, random.ptr, sizeof(this->server_random));
165
f154e304 166 if (!this->tls->set_version(this->tls, version))
4ef946dd 167 {
f154e304
MW
168 DBG1(DBG_TLS, "negotiated version %N not supported",
169 tls_version_names, version);
e6f3ef13
MW
170 this->alert->add(this->alert, TLS_FATAL, TLS_PROTOCOL_VERSION);
171 return NEED_MORE;
3e962b08 172 }
6a5c86b7
MW
173
174 if (chunk_equals(this->session, session))
18010de2 175 {
6a5c86b7
MW
176 suite = this->crypto->resume_session(this->crypto, session, this->server,
177 chunk_from_thing(this->client_random),
178 chunk_from_thing(this->server_random));
179 if (suite)
180 {
181 DBG1(DBG_TLS, "resumed %N using suite %N",
182 tls_version_names, version, tls_cipher_suite_names, suite);
183 this->resume = TRUE;
184 }
185 }
186 if (!suite)
187 {
188 suite = cipher;
189 if (!this->crypto->select_cipher_suite(this->crypto, &suite, 1, KEY_ANY))
190 {
191 DBG1(DBG_TLS, "received TLS cipher suite %N inacceptable",
192 tls_cipher_suite_names, suite);
193 this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
194 return NEED_MORE;
195 }
196 DBG1(DBG_TLS, "negotiated %N using suite %N",
197 tls_version_names, version, tls_cipher_suite_names, suite);
198 free(this->session.ptr);
199 this->session = chunk_clone(session);
18010de2 200 }
8fef06a6 201 this->state = STATE_HELLO_RECEIVED;
4ef946dd 202 return NEED_MORE;
3e962b08
MW
203}
204
c8114799
MW
205/**
206 * Check if a server certificate is acceptable for the given server identity
207 */
208static bool check_certificate(private_tls_peer_t *this, certificate_t *cert)
209{
210 identification_t *id;
211
212 if (cert->has_subject(cert, this->server))
213 {
214 return TRUE;
215 }
216 id = cert->get_subject(cert);
217 if (id->matches(id, this->server))
218 {
219 return TRUE;
220 }
221 if (cert->get_type(cert) == CERT_X509)
222 {
223 x509_t *x509 = (x509_t*)cert;
224 enumerator_t *enumerator;
225
226 enumerator = x509->create_subjectAltName_enumerator(x509);
227 while (enumerator->enumerate(enumerator, &id))
228 {
229 if (id->matches(id, this->server))
230 {
231 enumerator->destroy(enumerator);
232 return TRUE;
233 }
234 }
235 enumerator->destroy(enumerator);
236 }
237 DBG1(DBG_TLS, "server certificate does not match to '%Y'", this->server);
238 return FALSE;
239}
240
3e962b08
MW
241/**
242 * Process a Certificate message
243 */
4ef946dd 244static status_t process_certificate(private_tls_peer_t *this,
7e432eff 245 bio_reader_t *reader)
3e962b08 246{
4ef946dd 247 certificate_t *cert;
7e432eff 248 bio_reader_t *certs;
4ef946dd 249 chunk_t data;
3ddd164e
MW
250 bool first = TRUE;
251
84d67ead
MW
252 this->crypto->append_handshake(this->crypto,
253 TLS_CERTIFICATE, reader->peek(reader));
3e962b08 254
4ef946dd
MW
255 if (!reader->read_data24(reader, &data))
256 {
e6f3ef13
MW
257 DBG1(DBG_TLS, "certificate message header invalid");
258 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
259 return NEED_MORE;
4ef946dd 260 }
7e432eff 261 certs = bio_reader_create(data);
4ef946dd
MW
262 while (certs->remaining(certs))
263 {
264 if (!certs->read_data24(certs, &data))
3e962b08 265 {
e6f3ef13
MW
266 DBG1(DBG_TLS, "certificate message invalid");
267 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
4ef946dd 268 certs->destroy(certs);
e6f3ef13 269 return NEED_MORE;
3e962b08 270 }
4ef946dd 271 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
3ddd164e 272 BUILD_BLOB_ASN1_DER, data, BUILD_END);
4ef946dd 273 if (cert)
3e962b08 274 {
3ddd164e
MW
275 if (first)
276 {
c8114799
MW
277 if (!check_certificate(this, cert))
278 {
279 cert->destroy(cert);
280 certs->destroy(certs);
281 this->alert->add(this->alert, TLS_FATAL, TLS_ACCESS_DENIED);
282 return NEED_MORE;
283 }
3ddd164e 284 this->server_auth->add(this->server_auth,
400df4ca 285 AUTH_HELPER_SUBJECT_CERT, cert);
3c19b346 286 DBG1(DBG_TLS, "received TLS server certificate '%Y'",
3ddd164e
MW
287 cert->get_subject(cert));
288 first = FALSE;
289 }
290 else
291 {
3c19b346 292 DBG1(DBG_TLS, "received TLS intermediate certificate '%Y'",
3ddd164e
MW
293 cert->get_subject(cert));
294 this->server_auth->add(this->server_auth,
400df4ca 295 AUTH_HELPER_IM_CERT, cert);
3ddd164e
MW
296 }
297 }
298 else
299 {
3c19b346 300 DBG1(DBG_TLS, "parsing TLS certificate failed, skipped");
e6f3ef13 301 this->alert->add(this->alert, TLS_WARNING, TLS_BAD_CERTIFICATE);
3e962b08
MW
302 }
303 }
4ef946dd 304 certs->destroy(certs);
8fef06a6 305 this->state = STATE_CERT_RECEIVED;
3e962b08
MW
306 return NEED_MORE;
307}
308
da3f4a9f
MW
309/**
310 * Find a trusted public key to encrypt/verify key exchange data
311 */
312static public_key_t *find_public_key(private_tls_peer_t *this)
313{
314 public_key_t *public = NULL, *current;
18597950 315 certificate_t *cert, *found;
da3f4a9f
MW
316 enumerator_t *enumerator;
317 auth_cfg_t *auth;
318
319 cert = this->server_auth->get(this->server_auth, AUTH_HELPER_SUBJECT_CERT);
320 if (cert)
321 {
322 enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
323 KEY_ANY, cert->get_subject(cert), this->server_auth);
324 while (enumerator->enumerate(enumerator, &current, &auth))
325 {
18597950
TB
326 found = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
327 if (found && cert->equals(cert, found))
328 {
329 public = current->get_ref(current);
330 this->server_auth->merge(this->server_auth, auth, FALSE);
331 break;
332 }
da3f4a9f
MW
333 }
334 enumerator->destroy(enumerator);
335 }
336 return public;
337}
338
339/**
340 * Process a Key Exchange message using MODP Diffie Hellman
341 */
342static status_t process_modp_key_exchange(private_tls_peer_t *this,
7e432eff 343 bio_reader_t *reader)
da3f4a9f
MW
344{
345 chunk_t prime, generator, pub, chunk;
346 public_key_t *public;
347
348 chunk = reader->peek(reader);
349 if (!reader->read_data16(reader, &prime) ||
350 !reader->read_data16(reader, &generator) ||
351 !reader->read_data16(reader, &pub))
352 {
353 DBG1(DBG_TLS, "received invalid Server Key Exchange");
354 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
355 return NEED_MORE;
356 }
357 public = find_public_key(this);
358 if (!public)
359 {
360 DBG1(DBG_TLS, "no TLS public key found for server '%Y'", this->server);
361 this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN);
362 return NEED_MORE;
363 }
364
365 chunk.len = 2 + prime.len + 2 + generator.len + 2 + pub.len;
366 chunk = chunk_cat("ccc", chunk_from_thing(this->client_random),
367 chunk_from_thing(this->server_random), chunk);
368 if (!this->crypto->verify(this->crypto, public, reader, chunk))
369 {
370 public->destroy(public);
371 free(chunk.ptr);
372 DBG1(DBG_TLS, "verifying DH parameters failed");
373 this->alert->add(this->alert, TLS_FATAL, TLS_BAD_CERTIFICATE);
374 return NEED_MORE;
375 }
376 public->destroy(public);
377 free(chunk.ptr);
378
379 this->dh = lib->crypto->create_dh(lib->crypto, MODP_CUSTOM,
380 generator, prime);
381 if (!this->dh)
382 {
383 DBG1(DBG_TLS, "custom DH parameters not supported");
384 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
385 return NEED_MORE;
386 }
a777155f
MW
387 if (!this->dh->set_other_public_value(this->dh, pub))
388 {
389 DBG1(DBG_TLS, "applying DH public value failed");
390 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
391 return NEED_MORE;
392 }
da3f4a9f
MW
393
394 this->state = STATE_KEY_EXCHANGE_RECEIVED;
395 return NEED_MORE;
396}
397
3f7bb88b
MW
398/**
399 * Get the EC group for a TLS named curve
400 */
401static diffie_hellman_group_t curve_to_ec_group(private_tls_peer_t *this,
402 tls_named_curve_t curve)
403{
404 diffie_hellman_group_t group;
405 tls_named_curve_t current;
406 enumerator_t *enumerator;
407
408 enumerator = this->crypto->create_ec_enumerator(this->crypto);
409 while (enumerator->enumerate(enumerator, &group, &current))
410 {
411 if (current == curve)
412 {
413 enumerator->destroy(enumerator);
414 return group;
415 }
416 }
417 enumerator->destroy(enumerator);
418 return 0;
419}
5fc7297e
MW
420
421/**
422 * Process a Key Exchange message using EC Diffie Hellman
423 */
424static status_t process_ec_key_exchange(private_tls_peer_t *this,
7e432eff 425 bio_reader_t *reader)
5fc7297e
MW
426{
427 diffie_hellman_group_t group;
428 public_key_t *public;
429 u_int8_t type;
430 u_int16_t curve;
431 chunk_t pub, chunk;
432
433 chunk = reader->peek(reader);
434 if (!reader->read_uint8(reader, &type))
435 {
436 DBG1(DBG_TLS, "received invalid Server Key Exchange");
437 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
438 return NEED_MORE;
439 }
440 if (type != TLS_ECC_NAMED_CURVE)
441 {
442 DBG1(DBG_TLS, "ECDH curve type %N not supported",
443 tls_ecc_curve_type_names, type);
444 this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
445 return NEED_MORE;
446 }
447 if (!reader->read_uint16(reader, &curve) ||
e6cce7ff 448 !reader->read_data8(reader, &pub) || pub.len == 0)
5fc7297e
MW
449 {
450 DBG1(DBG_TLS, "received invalid Server Key Exchange");
451 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
452 return NEED_MORE;
453 }
3f7bb88b
MW
454
455 group = curve_to_ec_group(this, curve);
456 if (!group)
5fc7297e 457 {
3f7bb88b
MW
458 DBG1(DBG_TLS, "ECDH curve %N not supported",
459 tls_named_curve_names, curve);
460 this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
461 return NEED_MORE;
5fc7297e
MW
462 }
463
464 public = find_public_key(this);
465 if (!public)
466 {
467 DBG1(DBG_TLS, "no TLS public key found for server '%Y'", this->server);
468 this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN);
469 return NEED_MORE;
470 }
471
472 chunk.len = 4 + pub.len;
473 chunk = chunk_cat("ccc", chunk_from_thing(this->client_random),
474 chunk_from_thing(this->server_random), chunk);
475 if (!this->crypto->verify(this->crypto, public, reader, chunk))
476 {
477 public->destroy(public);
478 free(chunk.ptr);
479 DBG1(DBG_TLS, "verifying DH parameters failed");
480 this->alert->add(this->alert, TLS_FATAL, TLS_BAD_CERTIFICATE);
481 return NEED_MORE;
482 }
483 public->destroy(public);
484 free(chunk.ptr);
485
486 this->dh = lib->crypto->create_dh(lib->crypto, group);
487 if (!this->dh)
488 {
489 DBG1(DBG_TLS, "DH group %N not supported",
490 diffie_hellman_group_names, group);
491 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
492 return NEED_MORE;
493 }
e6cce7ff 494
ec7d4e70 495 if (pub.ptr[0] != TLS_ANSI_UNCOMPRESSED)
e6cce7ff
MW
496 {
497 DBG1(DBG_TLS, "DH point format '%N' not supported",
ec7d4e70 498 tls_ansi_point_format_names, pub.ptr[0]);
e6cce7ff
MW
499 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
500 return NEED_MORE;
501 }
a777155f
MW
502 if (!this->dh->set_other_public_value(this->dh, chunk_skip(pub, 1)))
503 {
504 DBG1(DBG_TLS, "applying DH public value failed");
505 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
506 return NEED_MORE;
507 }
5fc7297e
MW
508
509 this->state = STATE_KEY_EXCHANGE_RECEIVED;
510 return NEED_MORE;
511}
512
da3f4a9f
MW
513/**
514 * Process a Server Key Exchange
515 */
516static status_t process_key_exchange(private_tls_peer_t *this,
7e432eff 517 bio_reader_t *reader)
da3f4a9f
MW
518{
519 diffie_hellman_group_t group;
520
521 this->crypto->append_handshake(this->crypto,
522 TLS_SERVER_KEY_EXCHANGE, reader->peek(reader));
523
524 group = this->crypto->get_dh_group(this->crypto);
f4c98ae6 525 if (group == MODP_NONE)
da3f4a9f 526 {
f4c98ae6
MW
527 DBG1(DBG_TLS, "received Server Key Exchange, but not required "
528 "for current suite");
529 this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
530 return NEED_MORE;
531 }
532 if (diffie_hellman_group_is_ec(group))
533 {
534 return process_ec_key_exchange(this, reader);
da3f4a9f 535 }
f4c98ae6 536 return process_modp_key_exchange(this, reader);
da3f4a9f
MW
537}
538
3e962b08 539/**
69e8bb2e 540 * Process a Certificate Request message
3e962b08 541 */
7e432eff 542static status_t process_certreq(private_tls_peer_t *this, bio_reader_t *reader)
3e962b08 543{
4ef946dd 544 chunk_t types, hashsig, data;
7e432eff 545 bio_reader_t *authorities;
3e962b08 546 identification_t *id;
3ddd164e
MW
547 certificate_t *cert;
548
69e8bb2e
MW
549 if (!this->peer)
550 {
551 DBG1(DBG_TLS, "server requested a certificate, but client "
552 "authentication disabled");
69e8bb2e 553 }
84d67ead
MW
554 this->crypto->append_handshake(this->crypto,
555 TLS_CERTIFICATE_REQUEST, reader->peek(reader));
3e962b08 556
4ef946dd 557 if (!reader->read_data8(reader, &types))
3e962b08 558 {
e6f3ef13
MW
559 DBG1(DBG_TLS, "certreq message header invalid");
560 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
561 return NEED_MORE;
3e962b08 562 }
dbb7c030 563 this->cert_types = chunk_clone(types);
3e962b08
MW
564 if (this->tls->get_version(this->tls) >= TLS_1_2)
565 {
4ef946dd 566 if (!reader->read_data16(reader, &hashsig))
3e962b08 567 {
e6f3ef13
MW
568 DBG1(DBG_TLS, "certreq message invalid");
569 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
570 return NEED_MORE;
3e962b08 571 }
dbb7c030 572 this->hashsig = chunk_clone(hashsig);
3e962b08 573 }
4ef946dd 574 if (!reader->read_data16(reader, &data))
3e962b08 575 {
e6f3ef13
MW
576 DBG1(DBG_TLS, "certreq message invalid");
577 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
578 return NEED_MORE;
3e962b08 579 }
7e432eff 580 authorities = bio_reader_create(data);
4ef946dd 581 while (authorities->remaining(authorities))
3e962b08 582 {
4ef946dd 583 if (!authorities->read_data16(authorities, &data))
3e962b08 584 {
e6f3ef13
MW
585 DBG1(DBG_TLS, "certreq message invalid");
586 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
4ef946dd 587 authorities->destroy(authorities);
e6f3ef13 588 return NEED_MORE;
3e962b08 589 }
6a8f1a57 590 if (this->peer)
3ddd164e 591 {
6a8f1a57
MW
592 id = identification_create_from_encoding(ID_DER_ASN1_DN, data);
593 cert = lib->credmgr->get_cert(lib->credmgr,
594 CERT_X509, KEY_ANY, id, TRUE);
595 if (cert)
596 {
597 DBG1(DBG_TLS, "received TLS cert request for '%Y", id);
598 this->peer_auth->add(this->peer_auth, AUTH_RULE_CA_CERT, cert);
599 }
600 else
601 {
602 DBG1(DBG_TLS, "received TLS cert request for unknown CA '%Y'", id);
603 }
604 id->destroy(id);
3ddd164e 605 }
3e962b08 606 }
4ef946dd 607 authorities->destroy(authorities);
8fef06a6 608 this->state = STATE_CERTREQ_RECEIVED;
3e962b08
MW
609 return NEED_MORE;
610}
611
3ddd164e
MW
612/**
613 * Process Hello Done message
614 */
615static status_t process_hello_done(private_tls_peer_t *this,
7e432eff 616 bio_reader_t *reader)
3ddd164e 617{
84d67ead
MW
618 this->crypto->append_handshake(this->crypto,
619 TLS_SERVER_HELLO_DONE, reader->peek(reader));
3ddd164e
MW
620 this->state = STATE_HELLO_DONE;
621 return NEED_MORE;
622}
623
f139b578
MW
624/**
625 * Process finished message
626 */
7e432eff 627static status_t process_finished(private_tls_peer_t *this, bio_reader_t *reader)
f139b578 628{
84d67ead
MW
629 chunk_t received;
630 char buf[12];
110364b0 631
84d67ead 632 if (!reader->read_data(reader, sizeof(buf), &received))
110364b0 633 {
3c19b346 634 DBG1(DBG_TLS, "received server finished too short");
e6f3ef13
MW
635 this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
636 return NEED_MORE;
110364b0 637 }
84d67ead 638 if (!this->crypto->calculate_finished(this->crypto, "server finished", buf))
110364b0 639 {
3c19b346 640 DBG1(DBG_TLS, "calculating server finished failed");
e6f3ef13
MW
641 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
642 return NEED_MORE;
110364b0 643 }
84d67ead 644 if (!chunk_equals(received, chunk_from_thing(buf)))
110364b0 645 {
3c19b346 646 DBG1(DBG_TLS, "received server finished invalid");
e6f3ef13
MW
647 this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
648 return NEED_MORE;
110364b0 649 }
6a5c86b7
MW
650 this->state = STATE_FINISHED_RECEIVED;
651 this->crypto->append_handshake(this->crypto, TLS_FINISHED, received);
652
110364b0 653 return NEED_MORE;
f139b578
MW
654}
655
4c0c2283 656METHOD(tls_handshake_t, process, status_t,
7e432eff 657 private_tls_peer_t *this, tls_handshake_type_t type, bio_reader_t *reader)
4c0c2283 658{
8fef06a6
MW
659 tls_handshake_type_t expected;
660
3e962b08
MW
661 switch (this->state)
662 {
663 case STATE_HELLO_SENT:
8fef06a6
MW
664 if (type == TLS_SERVER_HELLO)
665 {
666 return process_server_hello(this, reader);
667 }
668 expected = TLS_SERVER_HELLO;
669 break;
670 case STATE_HELLO_RECEIVED:
671 if (type == TLS_CERTIFICATE)
3e962b08 672 {
8fef06a6 673 return process_certificate(this, reader);
3e962b08 674 }
8fef06a6
MW
675 expected = TLS_CERTIFICATE;
676 break;
677 case STATE_CERT_RECEIVED:
da3f4a9f
MW
678 if (type == TLS_SERVER_KEY_EXCHANGE)
679 {
680 return process_key_exchange(this, reader);
681 }
682 /* fall through since TLS_SERVER_KEY_EXCHANGE is optional */
683 case STATE_KEY_EXCHANGE_RECEIVED:
8fef06a6
MW
684 if (type == TLS_CERTIFICATE_REQUEST)
685 {
686 return process_certreq(this, reader);
687 }
2de481e3
MW
688 /* no cert request, server does not want to authenticate us */
689 DESTROY_IF(this->peer);
69e8bb2e 690 this->peer = NULL;
b4d30a42 691 /* fall through since TLS_CERTIFICATE_REQUEST is optional */
8fef06a6
MW
692 case STATE_CERTREQ_RECEIVED:
693 if (type == TLS_SERVER_HELLO_DONE)
694 {
695 return process_hello_done(this, reader);
696 }
697 expected = TLS_SERVER_HELLO_DONE;
3e962b08 698 break;
f139b578 699 case STATE_CIPHERSPEC_CHANGED_IN:
8fef06a6 700 if (type == TLS_FINISHED)
f139b578 701 {
8fef06a6 702 return process_finished(this, reader);
f139b578 703 }
8fef06a6 704 expected = TLS_FINISHED;
f139b578 705 break;
3e962b08 706 default:
3c19b346 707 DBG1(DBG_TLS, "TLS %N not expected in current state",
8fef06a6 708 tls_handshake_type_names, type);
e6f3ef13
MW
709 this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE);
710 return NEED_MORE;
3e962b08 711 }
3c19b346 712 DBG1(DBG_TLS, "TLS %N expected, but received %N",
8fef06a6 713 tls_handshake_type_names, expected, tls_handshake_type_names, type);
e6f3ef13
MW
714 this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE);
715 return NEED_MORE;
4c0c2283
MW
716}
717
698674c7
MW
718/**
719 * Send a client hello
720 */
8fef06a6 721static status_t send_client_hello(private_tls_peer_t *this,
7e432eff 722 tls_handshake_type_t *type, bio_writer_t *writer)
698674c7 723{
7ea87db0 724 tls_cipher_suite_t *suites;
7e432eff 725 bio_writer_t *extensions, *curves = NULL;
7ea87db0 726 tls_version_t version;
3f7bb88b
MW
727 tls_named_curve_t curve;
728 enumerator_t *enumerator;
3a1640de 729 int count, i;
698674c7
MW
730 rng_t *rng;
731
18010de2 732 htoun32(&this->client_random, time(NULL));
698674c7 733 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
126eb2af
TB
734 if (!rng ||
735 !rng->get_bytes(rng, sizeof(this->client_random) - 4,
736 this->client_random + 4))
698674c7 737 {
126eb2af 738 DBG1(DBG_TLS, "failed to generate client random");
e6f3ef13 739 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
126eb2af 740 DESTROY_IF(rng);
e6f3ef13 741 return NEED_MORE;
698674c7 742 }
3a1640de
MW
743 rng->destroy(rng);
744
7ea87db0
AS
745 /* TLS version */
746 version = this->tls->get_version(this->tls);
b37080f8 747 this->hello_version = version;
7ea87db0 748 writer->write_uint16(writer, version);
18010de2 749 writer->write_data(writer, chunk_from_thing(this->client_random));
7ea87db0 750
6a5c86b7
MW
751 /* session identifier */
752 this->session = this->crypto->get_session(this->crypto, this->server);
753 writer->write_data8(writer, this->session);
3a1640de 754
7ea87db0
AS
755 /* add TLS cipher suites */
756 count = this->crypto->get_cipher_suites(this->crypto, &suites);
3a1640de
MW
757 writer->write_uint16(writer, count * 2);
758 for (i = 0; i < count; i++)
759 {
7ea87db0 760 writer->write_uint16(writer, suites[i]);
3a1640de 761 }
7ea87db0 762
3a1640de
MW
763 /* NULL compression only */
764 writer->write_uint8(writer, 1);
765 writer->write_uint8(writer, 0);
766
7e432eff 767 extensions = bio_writer_create(32);
37a59a8f 768
06109c47
MW
769 extensions->write_uint16(extensions, TLS_EXT_SIGNATURE_ALGORITHMS);
770 this->crypto->get_signature_algorithms(this->crypto, extensions);
37a59a8f 771
3f7bb88b
MW
772 /* add supported Elliptic Curves, if any */
773 enumerator = this->crypto->create_ec_enumerator(this->crypto);
774 while (enumerator->enumerate(enumerator, NULL, &curve))
775 {
776 if (!curves)
777 {
778 extensions->write_uint16(extensions, TLS_EXT_ELLIPTIC_CURVES);
7e432eff 779 curves = bio_writer_create(16);
3f7bb88b
MW
780 }
781 curves->write_uint16(curves, curve);
782 }
783 enumerator->destroy(enumerator);
784 if (curves)
785 {
07f826af 786 curves->wrap16(curves);
3f7bb88b
MW
787 extensions->write_data16(extensions, curves->get_buf(curves));
788 curves->destroy(curves);
31c65eb3
MW
789
790 /* if we support curves, add point format extension */
791 extensions->write_uint16(extensions, TLS_EXT_EC_POINT_FORMATS);
792 extensions->write_uint16(extensions, 2);
793 extensions->write_uint8(extensions, 1);
794 extensions->write_uint8(extensions, TLS_EC_POINT_UNCOMPRESSED);
3f7bb88b 795 }
1c21f47a
MW
796 if (this->server->get_type(this->server) == ID_FQDN)
797 {
7e432eff 798 bio_writer_t *names;
1c21f47a
MW
799
800 DBG2(DBG_TLS, "sending Server Name Indication for '%Y'", this->server);
801
7e432eff 802 names = bio_writer_create(8);
1c21f47a
MW
803 names->write_uint8(names, TLS_NAME_TYPE_HOST_NAME);
804 names->write_data16(names, this->server->get_encoding(this->server));
805 names->wrap16(names);
806 extensions->write_uint16(extensions, TLS_EXT_SERVER_NAME);
807 extensions->write_data16(extensions, names->get_buf(names));
808 names->destroy(names);
809 }
37a59a8f 810
06109c47
MW
811 writer->write_data16(writer, extensions->get_buf(extensions));
812 extensions->destroy(extensions);
813
3a1640de 814 *type = TLS_CLIENT_HELLO;
3e962b08 815 this->state = STATE_HELLO_SENT;
84d67ead 816 this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
3ddd164e
MW
817 return NEED_MORE;
818}
819
dbb7c030
MW
820/**
821 * Find a private key suitable to sign Certificate Verify
822 */
823static private_key_t *find_private_key(private_tls_peer_t *this)
824{
825 private_key_t *key = NULL;
7e432eff 826 bio_reader_t *reader;
dbb7c030
MW
827 key_type_t type;
828 u_int8_t cert;
829
830 if (!this->peer)
831 {
832 return NULL;
833 }
7e432eff 834 reader = bio_reader_create(this->cert_types);
dbb7c030
MW
835 while (reader->remaining(reader) && reader->read_uint8(reader, &cert))
836 {
837 switch (cert)
838 {
839 case TLS_RSA_SIGN:
840 type = KEY_RSA;
841 break;
842 case TLS_ECDSA_SIGN:
843 type = KEY_ECDSA;
844 break;
845 default:
846 continue;
847 }
848 key = lib->credmgr->get_private(lib->credmgr, type,
849 this->peer, this->peer_auth);
850 if (key)
851 {
852 break;
853 }
854 }
855 reader->destroy(reader);
856 return key;
857}
858
3ddd164e
MW
859/**
860 * Send Certificate
861 */
862static status_t send_certificate(private_tls_peer_t *this,
7e432eff 863 tls_handshake_type_t *type, bio_writer_t *writer)
3ddd164e
MW
864{
865 enumerator_t *enumerator;
866 certificate_t *cert;
867 auth_rule_t rule;
7e432eff 868 bio_writer_t *certs;
3ddd164e
MW
869 chunk_t data;
870
dbb7c030 871 this->private = find_private_key(this);
3ddd164e
MW
872 if (!this->private)
873 {
2db8b58f
MW
874 DBG1(DBG_TLS, "no TLS peer certificate found for '%Y', "
875 "skipping client authentication", this->peer);
2de481e3 876 this->peer->destroy(this->peer);
2db8b58f 877 this->peer = NULL;
3ddd164e
MW
878 }
879
880 /* generate certificate payload */
7e432eff 881 certs = bio_writer_create(256);
2db8b58f 882 if (this->peer)
3ddd164e 883 {
2db8b58f
MW
884 cert = this->peer_auth->get(this->peer_auth, AUTH_RULE_SUBJECT_CERT);
885 if (cert)
3ddd164e 886 {
0b71bc7a
MW
887 if (cert->get_encoding(cert, CERT_ASN1_DER, &data))
888 {
2db8b58f 889 DBG1(DBG_TLS, "sending TLS peer certificate '%Y'",
0b71bc7a
MW
890 cert->get_subject(cert));
891 certs->write_data24(certs, data);
892 free(data.ptr);
893 }
3ddd164e 894 }
2db8b58f
MW
895 enumerator = this->peer_auth->create_enumerator(this->peer_auth);
896 while (enumerator->enumerate(enumerator, &rule, &cert))
897 {
898 if (rule == AUTH_RULE_IM_CERT)
899 {
900 if (cert->get_encoding(cert, CERT_ASN1_DER, &data))
901 {
902 DBG1(DBG_TLS, "sending TLS intermediate certificate '%Y'",
903 cert->get_subject(cert));
904 certs->write_data24(certs, data);
905 free(data.ptr);
906 }
907 }
908 }
909 enumerator->destroy(enumerator);
3ddd164e 910 }
3ddd164e
MW
911
912 writer->write_data24(writer, certs->get_buf(certs));
913 certs->destroy(certs);
914
915 *type = TLS_CERTIFICATE;
916 this->state = STATE_CERT_SENT;
84d67ead 917 this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
3ddd164e
MW
918 return NEED_MORE;
919}
920
921/**
da3f4a9f 922 * Send client key exchange, using premaster encryption
3ddd164e 923 */
da3f4a9f 924static status_t send_key_exchange_encrypt(private_tls_peer_t *this,
7e432eff 925 tls_handshake_type_t *type, bio_writer_t *writer)
3ddd164e 926{
da3f4a9f 927 public_key_t *public;
3ddd164e
MW
928 rng_t *rng;
929 char premaster[48];
930 chunk_t encrypted;
931
932 rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
126eb2af 933 if (!rng || !rng->get_bytes(rng, sizeof(premaster) - 2, premaster + 2))
3ddd164e 934 {
126eb2af 935 DBG1(DBG_TLS, "failed to generate TLS premaster secret");
a596006e 936 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
126eb2af 937 DESTROY_IF(rng);
da3f4a9f 938 return NEED_MORE;
3ddd164e 939 }
3ddd164e 940 rng->destroy(rng);
b37080f8 941 htoun16(premaster, this->hello_version);
3ddd164e 942
9020f7d0
MW
943 if (!this->crypto->derive_secrets(this->crypto, chunk_from_thing(premaster),
944 this->session, this->server,
945 chunk_from_thing(this->client_random),
946 chunk_from_thing(this->server_random)))
947 {
948 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
949 return NEED_MORE;
950 }
18010de2 951
da3f4a9f 952 public = find_public_key(this);
3ddd164e
MW
953 if (!public)
954 {
3c19b346 955 DBG1(DBG_TLS, "no TLS public key found for server '%Y'", this->server);
a596006e 956 this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN);
da3f4a9f 957 return NEED_MORE;
3ddd164e 958 }
33ddaaab
MW
959 if (!public->encrypt(public, ENCRYPT_RSA_PKCS1,
960 chunk_from_thing(premaster), &encrypted))
3ddd164e
MW
961 {
962 public->destroy(public);
3c19b346 963 DBG1(DBG_TLS, "encrypting TLS premaster secret failed");
a596006e 964 this->alert->add(this->alert, TLS_FATAL, TLS_BAD_CERTIFICATE);
da3f4a9f 965 return NEED_MORE;
3ddd164e
MW
966 }
967 public->destroy(public);
968
969 writer->write_data16(writer, encrypted);
970 free(encrypted.ptr);
971
972 *type = TLS_CLIENT_KEY_EXCHANGE;
973 this->state = STATE_KEY_EXCHANGE_SENT;
84d67ead 974 this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
3ddd164e
MW
975 return NEED_MORE;
976}
977
da3f4a9f
MW
978/**
979 * Send client key exchange, using DHE exchange
980 */
981static status_t send_key_exchange_dhe(private_tls_peer_t *this,
7e432eff 982 tls_handshake_type_t *type, bio_writer_t *writer)
da3f4a9f
MW
983{
984 chunk_t premaster, pub;
985
bace1d64 986 if (!this->dh->get_shared_secret(this->dh, &premaster))
da3f4a9f
MW
987 {
988 DBG1(DBG_TLS, "calculating premaster from DH failed");
989 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
990 return NEED_MORE;
991 }
9020f7d0
MW
992 if (!this->crypto->derive_secrets(this->crypto, premaster,
993 this->session, this->server,
994 chunk_from_thing(this->client_random),
995 chunk_from_thing(this->server_random)))
996 {
997 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
998 chunk_clear(&premaster);
999 return NEED_MORE;
1000 }
da3f4a9f
MW
1001 chunk_clear(&premaster);
1002
42431690
MW
1003 if (!this->dh->get_my_public_value(this->dh, &pub))
1004 {
1005 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
1006 return NEED_MORE;
1007 }
5fc7297e
MW
1008 if (this->dh->get_dh_group(this->dh) == MODP_CUSTOM)
1009 {
1010 writer->write_data16(writer, pub);
1011 }
1012 else
e6cce7ff
MW
1013 { /* ECP uses 8bit length header only, but a point format */
1014 writer->write_uint8(writer, pub.len + 1);
ec7d4e70 1015 writer->write_uint8(writer, TLS_ANSI_UNCOMPRESSED);
e6cce7ff 1016 writer->write_data(writer, pub);
5fc7297e 1017 }
da3f4a9f
MW
1018 free(pub.ptr);
1019
1020 *type = TLS_CLIENT_KEY_EXCHANGE;
1021 this->state = STATE_KEY_EXCHANGE_SENT;
1022 this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
1023 return NEED_MORE;
1024}
1025
1026/**
1027 * Send client key exchange, depending on suite
1028 */
1029static status_t send_key_exchange(private_tls_peer_t *this,
7e432eff 1030 tls_handshake_type_t *type, bio_writer_t *writer)
da3f4a9f
MW
1031{
1032 if (this->dh)
1033 {
1034 return send_key_exchange_dhe(this, type, writer);
1035 }
1036 return send_key_exchange_encrypt(this, type, writer);
1037}
1038
3ddd164e
MW
1039/**
1040 * Send certificate verify
1041 */
1042static status_t send_certificate_verify(private_tls_peer_t *this,
7e432eff 1043 tls_handshake_type_t *type, bio_writer_t *writer)
3ddd164e 1044{
84d67ead 1045 if (!this->private ||
dbb7c030
MW
1046 !this->crypto->sign_handshake(this->crypto, this->private,
1047 writer, this->hashsig))
3ddd164e 1048 {
3c19b346 1049 DBG1(DBG_TLS, "creating TLS Certificate Verify signature failed");
a596006e 1050 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
da3f4a9f 1051 return NEED_MORE;
3ddd164e 1052 }
3ddd164e
MW
1053
1054 *type = TLS_CERTIFICATE_VERIFY;
1055 this->state = STATE_VERIFY_SENT;
84d67ead 1056 this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
3ddd164e
MW
1057 return NEED_MORE;
1058}
1059
1060/**
1061 * Send Finished
1062 */
1063static status_t send_finished(private_tls_peer_t *this,
7e432eff 1064 tls_handshake_type_t *type, bio_writer_t *writer)
3ddd164e 1065{
84d67ead 1066 char buf[12];
18010de2 1067
84d67ead 1068 if (!this->crypto->calculate_finished(this->crypto, "client finished", buf))
18010de2 1069 {
3c19b346 1070 DBG1(DBG_TLS, "calculating client finished data failed");
a596006e 1071 this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
da3f4a9f 1072 return NEED_MORE;
18010de2 1073 }
18010de2 1074
84d67ead 1075 writer->write_data(writer, chunk_from_thing(buf));
18010de2 1076
3ddd164e
MW
1077 *type = TLS_FINISHED;
1078 this->state = STATE_FINISHED_SENT;
84d67ead 1079 this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
698674c7
MW
1080 return NEED_MORE;
1081}
1082
4c0c2283 1083METHOD(tls_handshake_t, build, status_t,
7e432eff 1084 private_tls_peer_t *this, tls_handshake_type_t *type, bio_writer_t *writer)
4c0c2283 1085{
698674c7
MW
1086 switch (this->state)
1087 {
1088 case STATE_INIT:
8fef06a6 1089 return send_client_hello(this, type, writer);
3ddd164e 1090 case STATE_HELLO_DONE:
69e8bb2e 1091 if (this->peer)
b4d30a42
AS
1092 {
1093 return send_certificate(this, type, writer);
1094 }
1095 /* otherwise fall through to next state */
3ddd164e
MW
1096 case STATE_CERT_SENT:
1097 return send_key_exchange(this, type, writer);
1098 case STATE_KEY_EXCHANGE_SENT:
69e8bb2e 1099 if (this->peer)
b4d30a42
AS
1100 {
1101 return send_certificate_verify(this, type, writer);
1102 }
1103 else
1104 {
1105 return INVALID_STATE;
1106 }
f139b578 1107 case STATE_CIPHERSPEC_CHANGED_OUT:
3ddd164e 1108 return send_finished(this, type, writer);
698674c7
MW
1109 default:
1110 return INVALID_STATE;
1111 }
4c0c2283
MW
1112}
1113
3ddd164e 1114METHOD(tls_handshake_t, cipherspec_changed, bool,
4caa3806 1115 private_tls_peer_t *this, bool inbound)
3ddd164e 1116{
4caa3806 1117 if (inbound)
3ddd164e 1118 {
6a5c86b7
MW
1119 if (this->resume)
1120 {
1121 return this->state == STATE_HELLO_RECEIVED;
1122 }
4caa3806
MW
1123 return this->state == STATE_FINISHED_SENT;
1124 }
1125 else
1126 {
6a5c86b7
MW
1127 if (this->resume)
1128 {
1129 return this->state == STATE_FINISHED_RECEIVED;
1130 }
4caa3806
MW
1131 if (this->peer)
1132 {
1133 return this->state == STATE_VERIFY_SENT;
1134 }
1135 return this->state == STATE_KEY_EXCHANGE_SENT;
3ddd164e 1136 }
3ddd164e
MW
1137}
1138
4caa3806
MW
1139METHOD(tls_handshake_t, change_cipherspec, void,
1140 private_tls_peer_t *this, bool inbound)
3ddd164e 1141{
4caa3806
MW
1142 this->crypto->change_cipher(this->crypto, inbound);
1143 if (inbound)
f139b578 1144 {
f139b578 1145 this->state = STATE_CIPHERSPEC_CHANGED_IN;
f139b578 1146 }
4caa3806
MW
1147 else
1148 {
1149 this->state = STATE_CIPHERSPEC_CHANGED_OUT;
1150 }
3ddd164e
MW
1151}
1152
1327839d
AS
1153METHOD(tls_handshake_t, finished, bool,
1154 private_tls_peer_t *this)
1155{
6a5c86b7
MW
1156 if (this->resume)
1157 {
1158 return this->state == STATE_FINISHED_SENT;
1159 }
1160 return this->state == STATE_FINISHED_RECEIVED;
1327839d
AS
1161}
1162
2de481e3
MW
1163METHOD(tls_handshake_t, get_peer_id, identification_t*,
1164 private_tls_peer_t *this)
1165{
1166 return this->peer;
1167}
1168
1169METHOD(tls_handshake_t, get_server_id, identification_t*,
1170 private_tls_peer_t *this)
1171{
1172 return this->server;
1173}
1174
666c5523
MW
1175METHOD(tls_handshake_t, get_auth, auth_cfg_t*,
1176 private_tls_peer_t *this)
1177{
1178 return this->server_auth;
1179}
1180
4c0c2283
MW
1181METHOD(tls_handshake_t, destroy, void,
1182 private_tls_peer_t *this)
1183{
3ddd164e 1184 DESTROY_IF(this->private);
da3f4a9f 1185 DESTROY_IF(this->dh);
2de481e3
MW
1186 DESTROY_IF(this->peer);
1187 this->server->destroy(this->server);
3ddd164e
MW
1188 this->peer_auth->destroy(this->peer_auth);
1189 this->server_auth->destroy(this->server_auth);
dbb7c030
MW
1190 free(this->hashsig.ptr);
1191 free(this->cert_types.ptr);
6a5c86b7 1192 free(this->session.ptr);
4c0c2283
MW
1193 free(this);
1194}
1195
1196/**
1197 * See header
1198 */
e6f3ef13 1199tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert,
3ddd164e 1200 identification_t *peer, identification_t *server)
4c0c2283
MW
1201{
1202 private_tls_peer_t *this;
1203
1204 INIT(this,
ba31fe1f
MW
1205 .public = {
1206 .handshake = {
1207 .process = _process,
1208 .build = _build,
1209 .cipherspec_changed = _cipherspec_changed,
1210 .change_cipherspec = _change_cipherspec,
1211 .finished = _finished,
2de481e3
MW
1212 .get_peer_id = _get_peer_id,
1213 .get_server_id = _get_server_id,
666c5523 1214 .get_auth = _get_auth,
ba31fe1f
MW
1215 .destroy = _destroy,
1216 },
4c0c2283 1217 },
698674c7 1218 .state = STATE_INIT,
3e962b08 1219 .tls = tls,
536dbc00 1220 .crypto = crypto,
e6f3ef13 1221 .alert = alert,
2de481e3
MW
1222 .peer = peer ? peer->clone(peer) : NULL,
1223 .server = server->clone(server),
3ddd164e
MW
1224 .peer_auth = auth_cfg_create(),
1225 .server_auth = auth_cfg_create(),
4c0c2283
MW
1226 );
1227
1228 return &this->public;
1229}