blob: a1aeeea9c9a454e2bbcdbc27238b4eb57c114a64 [file] [log] [blame]
Steven Valdez143e8b32016-07-11 13:19:03 -04001/* Copyright (c) 2016, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15#include <openssl/ssl.h>
16
17#include <assert.h>
18#include <string.h>
19
20#include <openssl/bytestring.h>
21#include <openssl/digest.h>
22#include <openssl/err.h>
23#include <openssl/mem.h>
24#include <openssl/rand.h>
25#include <openssl/stack.h>
26
27#include "internal.h"
28
29
30enum server_hs_state_t {
31 state_process_client_hello = 0,
David Benjamin25fe85b2016-08-09 20:00:32 -040032 state_select_parameters,
Steven Valdez5440fe02016-07-18 12:40:30 -040033 state_send_hello_retry_request,
34 state_flush_hello_retry_request,
35 state_process_second_client_hello,
Steven Valdez143e8b32016-07-11 13:19:03 -040036 state_send_server_hello,
37 state_send_encrypted_extensions,
38 state_send_certificate_request,
39 state_send_server_certificate,
40 state_send_server_certificate_verify,
41 state_complete_server_certificate_verify,
42 state_send_server_finished,
43 state_flush,
Steven Valdez143e8b32016-07-11 13:19:03 -040044 state_process_client_certificate,
45 state_process_client_certificate_verify,
46 state_process_client_finished,
Steven Valdez1e6f11a2016-07-27 11:10:52 -040047 state_send_new_session_ticket,
48 state_flush_new_session_ticket,
Steven Valdez143e8b32016-07-11 13:19:03 -040049 state_done,
50};
51
Steven Valdez5440fe02016-07-18 12:40:30 -040052static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
53
54static int resolve_psk_secret(SSL *ssl) {
55 SSL_HANDSHAKE *hs = ssl->s3->hs;
56
57 if (ssl->s3->tmp.new_cipher->algorithm_auth != SSL_aPSK) {
58 return tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len);
59 }
60
61 /* TODO(davidben): Support PSK. */
62 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
63 return 0;
64}
65
66static int resolve_ecdhe_secret(SSL *ssl, int *out_need_retry,
67 struct ssl_early_callback_ctx *early_ctx) {
68 *out_need_retry = 0;
69 SSL_HANDSHAKE *hs = ssl->s3->hs;
70
71 if (ssl->s3->tmp.new_cipher->algorithm_mkey != SSL_kECDHE) {
72 return tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len);
73 }
74
Steven Valdez5440fe02016-07-18 12:40:30 -040075 CBS key_share;
David Benjamincec73442016-08-02 17:41:33 -040076 if (!ssl_early_callback_get_extension(early_ctx, &key_share,
77 TLSEXT_TYPE_key_share)) {
Steven Valdez5440fe02016-07-18 12:40:30 -040078 OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
79 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
80 return ssl_hs_error;
81 }
82
Steven Valdez5440fe02016-07-18 12:40:30 -040083 int found_key_share;
84 uint8_t *dhe_secret;
85 size_t dhe_secret_len;
86 uint8_t alert;
Steven Valdez7259f2f2016-08-02 16:55:05 -040087 if (!ssl_ext_key_share_parse_clienthello(ssl, &found_key_share, &dhe_secret,
88 &dhe_secret_len, &alert,
89 &key_share)) {
Steven Valdez5440fe02016-07-18 12:40:30 -040090 ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
91 return 0;
92 }
93
94 if (!found_key_share) {
95 *out_need_retry = 1;
96 return 0;
97 }
98
99 int ok = tls13_advance_key_schedule(ssl, dhe_secret, dhe_secret_len);
100 OPENSSL_free(dhe_secret);
101 return ok;
102}
103
Steven Valdez143e8b32016-07-11 13:19:03 -0400104static enum ssl_hs_wait_t do_process_client_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
105 if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
106 return ssl_hs_error;
107 }
108
David Benjamine14ff062016-08-09 16:21:24 -0400109 struct ssl_early_callback_ctx client_hello;
110 if (!ssl_early_callback_init(ssl, &client_hello, ssl->init_msg,
David Benjamind7573dc2016-07-20 19:05:22 +0200111 ssl->init_num)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400112 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
113 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
114 return ssl_hs_error;
115 }
116
Steven Valdez143e8b32016-07-11 13:19:03 -0400117 assert(ssl->s3->have_version);
118
119 /* Load the client random. */
David Benjamine14ff062016-08-09 16:21:24 -0400120 if (client_hello.random_len != SSL3_RANDOM_SIZE) {
121 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
122 return -1;
123 }
124 memcpy(ssl->s3->client_random, client_hello.random, client_hello.random_len);
Steven Valdez143e8b32016-07-11 13:19:03 -0400125
Steven Valdez87eab492016-06-27 16:34:59 -0400126 SSL_set_session(ssl, NULL);
Steven Valdez143e8b32016-07-11 13:19:03 -0400127 if (!ssl_get_new_session(ssl, 1 /* server */)) {
128 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
129 return ssl_hs_error;
130 }
131
132 if (ssl->ctx->dos_protection_cb != NULL &&
David Benjamine14ff062016-08-09 16:21:24 -0400133 ssl->ctx->dos_protection_cb(&client_hello) == 0) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400134 /* Connection rejected for DOS reasons. */
135 OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
136 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ACCESS_DENIED);
137 return ssl_hs_error;
138 }
139
Steven Valdez143e8b32016-07-11 13:19:03 -0400140 /* TLS 1.3 requires the peer only advertise the null compression. */
David Benjamine14ff062016-08-09 16:21:24 -0400141 if (client_hello.compression_methods_len != 1 ||
142 client_hello.compression_methods[0] != 0) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400143 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMPRESSION_LIST);
144 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
145 return ssl_hs_error;
146 }
147
148 /* TLS extensions. */
David Benjamine14ff062016-08-09 16:21:24 -0400149 if (!ssl_parse_clienthello_tlsext(ssl, &client_hello)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400150 OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
151 return ssl_hs_error;
152 }
153
David Benjamin25fe85b2016-08-09 20:00:32 -0400154 hs->state = state_select_parameters;
155 return ssl_hs_ok;
156}
157
158static enum ssl_hs_wait_t do_select_parameters(SSL *ssl, SSL_HANDSHAKE *hs) {
159 /* Call |cert_cb| to update server certificates if required. */
Steven Valdez143e8b32016-07-11 13:19:03 -0400160 if (ssl->cert->cert_cb != NULL) {
161 int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
162 if (rv == 0) {
163 OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
164 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
165 return ssl_hs_error;
166 }
167 if (rv < 0) {
David Benjamin25fe85b2016-08-09 20:00:32 -0400168 hs->state = state_select_parameters;
Steven Valdez143e8b32016-07-11 13:19:03 -0400169 return ssl_hs_x509_lookup;
170 }
171 }
172
David Benjamin25fe85b2016-08-09 20:00:32 -0400173 struct ssl_early_callback_ctx client_hello;
174 if (!ssl_early_callback_init(ssl, &client_hello, ssl->init_msg,
175 ssl->init_num)) {
176 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
177 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
178 return ssl_hs_error;
179 }
180
Steven Valdez143e8b32016-07-11 13:19:03 -0400181 const SSL_CIPHER *cipher =
David Benjaminfddbadc2016-08-09 19:53:00 -0400182 ssl3_choose_cipher(ssl, &client_hello, ssl_get_cipher_preferences(ssl));
Steven Valdez143e8b32016-07-11 13:19:03 -0400183 if (cipher == NULL) {
184 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
185 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
186 return ssl_hs_error;
187 }
188
Steven Valdez87eab492016-06-27 16:34:59 -0400189 ssl->s3->new_session->cipher = cipher;
Steven Valdez143e8b32016-07-11 13:19:03 -0400190 ssl->s3->tmp.new_cipher = cipher;
191
David Benjamin613fe3b2016-07-22 17:39:29 +0200192 ssl->method->received_flight(ssl);
193
Steven Valdez143e8b32016-07-11 13:19:03 -0400194 /* The PRF hash is now known. Set up the key schedule and hash the
195 * ClientHello. */
Steven Valdez143e8b32016-07-11 13:19:03 -0400196 size_t hash_len =
197 EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
198 if (!tls13_init_key_schedule(ssl, kZeroes, hash_len)) {
199 return ssl_hs_error;
200 }
201
202 /* Resolve PSK and incorporate it into the secret. */
Steven Valdez5440fe02016-07-18 12:40:30 -0400203 if (!resolve_psk_secret(ssl)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400204 return ssl_hs_error;
205 }
206
207 /* Resolve ECDHE and incorporate it into the secret. */
Steven Valdez5440fe02016-07-18 12:40:30 -0400208 int need_retry;
David Benjamine14ff062016-08-09 16:21:24 -0400209 if (!resolve_ecdhe_secret(ssl, &need_retry, &client_hello)) {
Steven Valdez5440fe02016-07-18 12:40:30 -0400210 if (need_retry) {
211 hs->state = state_send_hello_retry_request;
212 return ssl_hs_ok;
Steven Valdez143e8b32016-07-11 13:19:03 -0400213 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400214 return ssl_hs_error;
215 }
Steven Valdez143e8b32016-07-11 13:19:03 -0400216
Steven Valdez5440fe02016-07-18 12:40:30 -0400217 hs->state = state_send_server_hello;
218 return ssl_hs_ok;
219}
Steven Valdez143e8b32016-07-11 13:19:03 -0400220
Steven Valdez5440fe02016-07-18 12:40:30 -0400221static enum ssl_hs_wait_t do_send_hello_retry_request(SSL *ssl,
222 SSL_HANDSHAKE *hs) {
223 CBB cbb, body, extensions;
224 uint16_t group_id;
225 if (!ssl->method->init_message(ssl, &cbb, &body,
226 SSL3_MT_HELLO_RETRY_REQUEST) ||
227 !CBB_add_u16(&body, ssl->version) ||
228 !CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
229 !tls1_get_shared_group(ssl, &group_id) ||
230 !CBB_add_u16(&body, group_id) ||
231 !CBB_add_u16_length_prefixed(&body, &extensions) ||
232 !ssl->method->finish_message(ssl, &cbb)) {
233 CBB_cleanup(&cbb);
234 return ssl_hs_error;
235 }
236
237 hs->state = state_flush_hello_retry_request;
238 return ssl_hs_write_message;
239}
240
241static enum ssl_hs_wait_t do_flush_hello_retry_request(SSL *ssl,
242 SSL_HANDSHAKE *hs) {
243 hs->state = state_process_second_client_hello;
244 return ssl_hs_flush_and_read_message;
245}
246
247static enum ssl_hs_wait_t do_process_second_client_hello(SSL *ssl,
248 SSL_HANDSHAKE *hs) {
249 if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
250 return ssl_hs_error;
251 }
252
David Benjamine14ff062016-08-09 16:21:24 -0400253 struct ssl_early_callback_ctx client_hello;
254 if (!ssl_early_callback_init(ssl, &client_hello, ssl->init_msg,
David Benjamind7573dc2016-07-20 19:05:22 +0200255 ssl->init_num)) {
Steven Valdez5440fe02016-07-18 12:40:30 -0400256 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
257 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
258 return ssl_hs_error;
259 }
260
261 int need_retry;
David Benjamine14ff062016-08-09 16:21:24 -0400262 if (!resolve_ecdhe_secret(ssl, &need_retry, &client_hello)) {
Steven Valdez5440fe02016-07-18 12:40:30 -0400263 if (need_retry) {
264 /* Only send one HelloRetryRequest. */
265 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
266 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
Steven Valdez143e8b32016-07-11 13:19:03 -0400267 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400268 return ssl_hs_error;
269 }
270
271 if (!ssl->method->hash_current_message(ssl)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400272 return ssl_hs_error;
273 }
274
David Benjamin613fe3b2016-07-22 17:39:29 +0200275 ssl->method->received_flight(ssl);
Steven Valdez143e8b32016-07-11 13:19:03 -0400276 hs->state = state_send_server_hello;
277 return ssl_hs_ok;
278}
279
280static enum ssl_hs_wait_t do_send_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
281 CBB cbb, body, extensions;
282 if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
283 !CBB_add_u16(&body, ssl->version) ||
284 !RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) ||
285 !CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
286 !CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
287 !CBB_add_u16_length_prefixed(&body, &extensions) ||
Steven Valdez7259f2f2016-08-02 16:55:05 -0400288 !ssl_ext_key_share_add_serverhello(ssl, &extensions) ||
Steven Valdez143e8b32016-07-11 13:19:03 -0400289 !ssl->method->finish_message(ssl, &cbb)) {
290 CBB_cleanup(&cbb);
291 return ssl_hs_error;
292 }
293
294 hs->state = state_send_encrypted_extensions;
295 return ssl_hs_write_message;
296}
297
298static enum ssl_hs_wait_t do_send_encrypted_extensions(SSL *ssl,
299 SSL_HANDSHAKE *hs) {
300 if (!tls13_set_handshake_traffic(ssl)) {
301 return ssl_hs_error;
302 }
303
304 CBB cbb, body;
305 if (!ssl->method->init_message(ssl, &cbb, &body,
306 SSL3_MT_ENCRYPTED_EXTENSIONS) ||
307 !ssl_add_serverhello_tlsext(ssl, &body) ||
308 !ssl->method->finish_message(ssl, &cbb)) {
309 CBB_cleanup(&cbb);
310 return ssl_hs_error;
311 }
312
313 hs->state = state_send_certificate_request;
314 return ssl_hs_write_message;
315}
316
317static enum ssl_hs_wait_t do_send_certificate_request(SSL *ssl,
318 SSL_HANDSHAKE *hs) {
319 /* Determine whether to request a client certificate. */
320 ssl->s3->tmp.cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
321 /* CertificateRequest may only be sent in certificate-based ciphers. */
322 if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
323 ssl->s3->tmp.cert_request = 0;
324 }
325
326 if (!ssl->s3->tmp.cert_request) {
327 /* Skip this state. */
328 hs->state = state_send_server_certificate;
329 return ssl_hs_ok;
330 }
331
332 CBB cbb, body, sigalgs_cbb;
333 if (!ssl->method->init_message(ssl, &cbb, &body,
334 SSL3_MT_CERTIFICATE_REQUEST) ||
335 !CBB_add_u8(&body, 0 /* no certificate_request_context. */)) {
336 goto err;
337 }
338
339 const uint16_t *sigalgs;
340 size_t sigalgs_len = tls12_get_psigalgs(ssl, &sigalgs);
341 if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) {
342 goto err;
343 }
344
345 for (size_t i = 0; i < sigalgs_len; i++) {
346 if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) {
347 goto err;
348 }
349 }
350
351 if (!ssl_add_client_CA_list(ssl, &body) ||
352 !CBB_add_u16(&body, 0 /* empty certificate_extensions. */) ||
353 !ssl->method->finish_message(ssl, &cbb)) {
354 goto err;
355 }
356
357 hs->state = state_send_server_certificate;
358 return ssl_hs_write_message;
359
360err:
361 CBB_cleanup(&cbb);
362 return ssl_hs_error;
363}
364
365static enum ssl_hs_wait_t do_send_server_certificate(SSL *ssl,
366 SSL_HANDSHAKE *hs) {
367 if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
368 hs->state = state_send_server_finished;
369 return ssl_hs_ok;
370 }
371
372 if (!ssl_has_certificate(ssl)) {
373 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
374 return ssl_hs_error;
375 }
376
377 if (!tls13_prepare_certificate(ssl)) {
378 return ssl_hs_error;
379 }
380
381 hs->state = state_send_server_certificate_verify;
382 return ssl_hs_write_message;
383}
384
385static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL *ssl,
386 SSL_HANDSHAKE *hs,
387 int is_first_run) {
388 switch (tls13_prepare_certificate_verify(ssl, is_first_run)) {
389 case ssl_private_key_success:
390 hs->state = state_send_server_finished;
391 return ssl_hs_write_message;
392
393 case ssl_private_key_retry:
394 hs->state = state_complete_server_certificate_verify;
395 return ssl_hs_private_key_operation;
396
397 case ssl_private_key_failure:
398 return ssl_hs_error;
399 }
400
401 assert(0);
402 return ssl_hs_error;
403}
404
405static enum ssl_hs_wait_t do_send_server_finished(SSL *ssl, SSL_HANDSHAKE *hs) {
406 if (!tls13_prepare_finished(ssl)) {
407 return ssl_hs_error;
408 }
409
410 hs->state = state_flush;
411 return ssl_hs_write_message;
412}
413
414static enum ssl_hs_wait_t do_flush(SSL *ssl, SSL_HANDSHAKE *hs) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400415 /* Update the secret to the master secret and derive traffic keys. */
Steven Valdez143e8b32016-07-11 13:19:03 -0400416 if (!tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len) ||
417 !tls13_derive_traffic_secret_0(ssl) ||
418 !tls13_set_traffic_key(ssl, type_data, evp_aead_seal,
419 hs->traffic_secret_0, hs->hash_len)) {
420 return ssl_hs_error;
421 }
422
423 hs->state = state_process_client_certificate;
David Benjaminf2401eb2016-07-18 22:25:05 +0200424 return ssl_hs_flush_and_read_message;
Steven Valdez143e8b32016-07-11 13:19:03 -0400425}
426
427static enum ssl_hs_wait_t do_process_client_certificate(SSL *ssl,
428 SSL_HANDSHAKE *hs) {
429 if (!ssl->s3->tmp.cert_request) {
430 /* Skip this state. */
431 hs->state = state_process_client_certificate_verify;
432 return ssl_hs_ok;
433 }
434
David Benjamin4087df92016-08-01 20:16:31 -0400435 const int allow_anonymous =
436 (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) == 0;
437
Steven Valdez143e8b32016-07-11 13:19:03 -0400438 if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
David Benjamin4087df92016-08-01 20:16:31 -0400439 !tls13_process_certificate(ssl, allow_anonymous) ||
Steven Valdez143e8b32016-07-11 13:19:03 -0400440 !ssl->method->hash_current_message(ssl)) {
441 return ssl_hs_error;
442 }
443
David Benjamin3ce43892016-08-01 19:41:34 -0400444 /* For historical reasons, the server's copy of the chain does not include the
445 * leaf while the client's does. */
446 if (sk_X509_num(ssl->s3->new_session->cert_chain) > 0) {
447 X509_free(sk_X509_shift(ssl->s3->new_session->cert_chain));
448 }
449
Steven Valdez143e8b32016-07-11 13:19:03 -0400450 hs->state = state_process_client_certificate_verify;
451 return ssl_hs_read_message;
452}
453
454static enum ssl_hs_wait_t do_process_client_certificate_verify(
455 SSL *ssl, SSL_HANDSHAKE *hs) {
Steven Valdez87eab492016-06-27 16:34:59 -0400456 if (ssl->s3->new_session->peer == NULL) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400457 /* Skip this state. */
458 hs->state = state_process_client_finished;
459 return ssl_hs_ok;
460 }
461
462 if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
463 !tls13_process_certificate_verify(ssl) ||
464 !ssl->method->hash_current_message(ssl)) {
465 return 0;
466 }
467
468 hs->state = state_process_client_finished;
469 return ssl_hs_read_message;
470}
471
472static enum ssl_hs_wait_t do_process_client_finished(SSL *ssl,
473 SSL_HANDSHAKE *hs) {
474 if (!tls13_check_message_type(ssl, SSL3_MT_FINISHED) ||
475 !tls13_process_finished(ssl) ||
476 !ssl->method->hash_current_message(ssl) ||
477 /* evp_aead_seal keys have already been switched. */
478 !tls13_set_traffic_key(ssl, type_data, evp_aead_open,
479 hs->traffic_secret_0, hs->hash_len) ||
480 !tls13_finalize_keys(ssl)) {
481 return ssl_hs_error;
482 }
483
David Benjamin613fe3b2016-07-22 17:39:29 +0200484 ssl->method->received_flight(ssl);
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400485 hs->state = state_send_new_session_ticket;
Steven Valdez143e8b32016-07-11 13:19:03 -0400486 return ssl_hs_ok;
487}
488
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400489static enum ssl_hs_wait_t do_send_new_session_ticket(SSL *ssl,
490 SSL_HANDSHAKE *hs) {
491 SSL_SESSION *session = ssl->s3->new_session;
Martin Kreichgauerbaafa4a2016-08-09 10:18:40 -0700492 session->tlsext_tick_lifetime_hint = session->timeout;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400493 session->ticket_flags = SSL_TICKET_ALLOW_DHE_RESUMPTION;
494 if (!RAND_bytes((uint8_t *)&session->ticket_age_add,
495 sizeof(session->ticket_age_add))) {
496 return 0;
497 }
498 session->ticket_age_add_valid = 1;
499
500 CBB cbb, body, ticket;
501 if (!ssl->method->init_message(ssl, &cbb, &body,
502 SSL3_MT_NEW_SESSION_TICKET) ||
Martin Kreichgauerbaafa4a2016-08-09 10:18:40 -0700503 !CBB_add_u32(&body, session->tlsext_tick_lifetime_hint) ||
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400504 !CBB_add_u32(&body, session->ticket_flags) ||
505 !CBB_add_u32(&body, session->ticket_age_add) ||
506 !CBB_add_u16(&body, 0 /* no ticket extensions */) ||
507 !CBB_add_u16_length_prefixed(&body, &ticket) ||
508 !ssl_encrypt_ticket(ssl, &ticket, session) ||
509 !ssl->method->finish_message(ssl, &cbb)) {
510 CBB_cleanup(&cbb);
511 return ssl_hs_error;
512 }
513
514 hs->session_tickets_sent++;
515
516 hs->state = state_flush_new_session_ticket;
517 return ssl_hs_write_message;
518}
519
520/* TLS 1.3 recommends single-use tickets, so issue multiple tickets in case the
521 * client makes several connections before getting a renewal. */
522static const int kNumTickets = 2;
523
524static enum ssl_hs_wait_t do_flush_new_session_ticket(SSL *ssl,
525 SSL_HANDSHAKE *hs) {
526 if (hs->session_tickets_sent >= kNumTickets) {
527 hs->state = state_done;
528 } else {
529 hs->state = state_send_new_session_ticket;
530 }
531 return ssl_hs_flush;
532}
533
Steven Valdez143e8b32016-07-11 13:19:03 -0400534enum ssl_hs_wait_t tls13_server_handshake(SSL *ssl) {
535 SSL_HANDSHAKE *hs = ssl->s3->hs;
536
537 while (hs->state != state_done) {
538 enum ssl_hs_wait_t ret = ssl_hs_error;
539 enum server_hs_state_t state = hs->state;
540 switch (state) {
541 case state_process_client_hello:
542 ret = do_process_client_hello(ssl, hs);
543 break;
David Benjamin25fe85b2016-08-09 20:00:32 -0400544 case state_select_parameters:
545 ret = do_select_parameters(ssl, hs);
546 break;
Steven Valdez5440fe02016-07-18 12:40:30 -0400547 case state_send_hello_retry_request:
548 ret = do_send_hello_retry_request(ssl, hs);
549 break;
550 case state_flush_hello_retry_request:
551 ret = do_flush_hello_retry_request(ssl, hs);
552 break;
553 case state_process_second_client_hello:
554 ret = do_process_second_client_hello(ssl, hs);
555 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400556 case state_send_server_hello:
557 ret = do_send_server_hello(ssl, hs);
558 break;
559 case state_send_encrypted_extensions:
560 ret = do_send_encrypted_extensions(ssl, hs);
561 break;
562 case state_send_certificate_request:
563 ret = do_send_certificate_request(ssl, hs);
564 break;
565 case state_send_server_certificate:
566 ret = do_send_server_certificate(ssl, hs);
567 break;
568 case state_send_server_certificate_verify:
569 ret = do_send_server_certificate_verify(ssl, hs, 1 /* first run */);
570 break;
571 case state_complete_server_certificate_verify:
572 ret = do_send_server_certificate_verify(ssl, hs, 0 /* complete */);
573 break;
574 case state_send_server_finished:
575 ret = do_send_server_finished(ssl, hs);
576 break;
577 case state_flush:
578 ret = do_flush(ssl, hs);
579 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400580 case state_process_client_certificate:
581 ret = do_process_client_certificate(ssl, hs);
582 break;
583 case state_process_client_certificate_verify:
584 ret = do_process_client_certificate_verify(ssl, hs);
585 break;
586 case state_process_client_finished:
587 ret = do_process_client_finished(ssl, hs);
588 break;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400589 case state_send_new_session_ticket:
590 ret = do_send_new_session_ticket(ssl, hs);
591 break;
592 case state_flush_new_session_ticket:
593 ret = do_flush_new_session_ticket(ssl, hs);
594 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400595 case state_done:
596 ret = ssl_hs_ok;
597 break;
598 }
599
600 if (ret != ssl_hs_ok) {
601 return ret;
602 }
603 }
604
605 return ssl_hs_ok;
606}