blob: 1f4475e8cecf12dfc27f0b0f9fc6ae0e8c4a82a7 [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
Steven Valdez4aa154e2016-07-29 14:32:55 -040061 uint8_t resumption_psk[EVP_MAX_MD_SIZE];
62 if (!tls13_resumption_psk(ssl, resumption_psk, hs->hash_len,
63 ssl->s3->new_session) ||
64 !tls13_advance_key_schedule(ssl, resumption_psk, hs->hash_len)) {
65 return 0;
66 }
67
68 return 1;
Steven Valdez5440fe02016-07-18 12:40:30 -040069}
70
71static int resolve_ecdhe_secret(SSL *ssl, int *out_need_retry,
72 struct ssl_early_callback_ctx *early_ctx) {
73 *out_need_retry = 0;
74 SSL_HANDSHAKE *hs = ssl->s3->hs;
75
76 if (ssl->s3->tmp.new_cipher->algorithm_mkey != SSL_kECDHE) {
77 return tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len);
78 }
79
Steven Valdez5440fe02016-07-18 12:40:30 -040080 CBS key_share;
David Benjamincec73442016-08-02 17:41:33 -040081 if (!ssl_early_callback_get_extension(early_ctx, &key_share,
82 TLSEXT_TYPE_key_share)) {
Steven Valdez5440fe02016-07-18 12:40:30 -040083 OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
84 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
85 return ssl_hs_error;
86 }
87
Steven Valdez5440fe02016-07-18 12:40:30 -040088 int found_key_share;
89 uint8_t *dhe_secret;
90 size_t dhe_secret_len;
91 uint8_t alert;
Steven Valdez7259f2f2016-08-02 16:55:05 -040092 if (!ssl_ext_key_share_parse_clienthello(ssl, &found_key_share, &dhe_secret,
93 &dhe_secret_len, &alert,
94 &key_share)) {
Steven Valdez5440fe02016-07-18 12:40:30 -040095 ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
96 return 0;
97 }
98
99 if (!found_key_share) {
100 *out_need_retry = 1;
101 return 0;
102 }
103
104 int ok = tls13_advance_key_schedule(ssl, dhe_secret, dhe_secret_len);
105 OPENSSL_free(dhe_secret);
106 return ok;
107}
108
Steven Valdez143e8b32016-07-11 13:19:03 -0400109static enum ssl_hs_wait_t do_process_client_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
110 if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
111 return ssl_hs_error;
112 }
113
David Benjamine14ff062016-08-09 16:21:24 -0400114 struct ssl_early_callback_ctx client_hello;
115 if (!ssl_early_callback_init(ssl, &client_hello, ssl->init_msg,
David Benjamind7573dc2016-07-20 19:05:22 +0200116 ssl->init_num)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400117 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
118 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
119 return ssl_hs_error;
120 }
121
Steven Valdez143e8b32016-07-11 13:19:03 -0400122 assert(ssl->s3->have_version);
123
124 /* Load the client random. */
David Benjamine14ff062016-08-09 16:21:24 -0400125 if (client_hello.random_len != SSL3_RANDOM_SIZE) {
126 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
127 return -1;
128 }
129 memcpy(ssl->s3->client_random, client_hello.random, client_hello.random_len);
Steven Valdez143e8b32016-07-11 13:19:03 -0400130
Steven Valdez4aa154e2016-07-29 14:32:55 -0400131 uint8_t alert = SSL_AD_DECODE_ERROR;
132 SSL_SESSION *session = NULL;
133 CBS pre_shared_key;
134 if (ssl_early_callback_get_extension(&client_hello, &pre_shared_key,
135 TLSEXT_TYPE_pre_shared_key) &&
136 !ssl_ext_pre_shared_key_parse_clienthello(ssl, &session, &alert,
137 &pre_shared_key)) {
138 ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
139 return 0;
140 }
141
142 uint16_t resumption_cipher;
143 if (session != NULL &&
144 /* We currently only support ECDHE-PSK resumption. */
145 ((session->ticket_flags & SSL_TICKET_ALLOW_DHE_RESUMPTION) == 0 ||
146 /* Only resume if the session's version matches. */
147 session->ssl_version != ssl->version ||
148 !ssl_cipher_get_ecdhe_psk_cipher(session->cipher, &resumption_cipher) ||
149 !ssl_client_cipher_list_contains_cipher(&client_hello,
150 resumption_cipher))) {
151 SSL_SESSION_free(session);
152 session = NULL;
153 }
154
155 if (session == NULL) {
156 if (!ssl_get_new_session(ssl, 1 /* server */)) {
157 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
158 return ssl_hs_error;
159 }
160 } else {
161 /* Only authentication information carries over in TLS 1.3. */
162 ssl->s3->new_session = SSL_SESSION_dup(session, SSL_SESSION_DUP_AUTH_ONLY);
163 if (ssl->s3->new_session == NULL) {
164 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
165 return ssl_hs_error;
166 }
167 ssl->s3->session_reused = 1;
168 ssl->verify_result = session->verify_result;
169 SSL_SESSION_free(session);
Steven Valdez143e8b32016-07-11 13:19:03 -0400170 }
171
172 if (ssl->ctx->dos_protection_cb != NULL &&
David Benjamine14ff062016-08-09 16:21:24 -0400173 ssl->ctx->dos_protection_cb(&client_hello) == 0) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400174 /* Connection rejected for DOS reasons. */
175 OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
176 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ACCESS_DENIED);
177 return ssl_hs_error;
178 }
179
Steven Valdez143e8b32016-07-11 13:19:03 -0400180 /* TLS 1.3 requires the peer only advertise the null compression. */
David Benjamine14ff062016-08-09 16:21:24 -0400181 if (client_hello.compression_methods_len != 1 ||
182 client_hello.compression_methods[0] != 0) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400183 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMPRESSION_LIST);
184 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
185 return ssl_hs_error;
186 }
187
188 /* TLS extensions. */
David Benjamine14ff062016-08-09 16:21:24 -0400189 if (!ssl_parse_clienthello_tlsext(ssl, &client_hello)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400190 OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
191 return ssl_hs_error;
192 }
193
David Benjamin25fe85b2016-08-09 20:00:32 -0400194 hs->state = state_select_parameters;
195 return ssl_hs_ok;
196}
197
198static enum ssl_hs_wait_t do_select_parameters(SSL *ssl, SSL_HANDSHAKE *hs) {
Steven Valdez4aa154e2016-07-29 14:32:55 -0400199 if (!ssl->s3->session_reused) {
200 /* Call |cert_cb| to update server certificates if required. */
201 if (ssl->cert->cert_cb != NULL) {
202 int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
203 if (rv == 0) {
204 OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
205 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
206 return ssl_hs_error;
207 }
208 if (rv < 0) {
209 hs->state = state_select_parameters;
210 return ssl_hs_x509_lookup;
211 }
Steven Valdez143e8b32016-07-11 13:19:03 -0400212 }
213 }
214
David Benjamin25fe85b2016-08-09 20:00:32 -0400215 struct ssl_early_callback_ctx client_hello;
216 if (!ssl_early_callback_init(ssl, &client_hello, ssl->init_msg,
217 ssl->init_num)) {
218 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
219 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
220 return ssl_hs_error;
221 }
222
Steven Valdez4aa154e2016-07-29 14:32:55 -0400223 if (!ssl->s3->session_reused) {
224 const SSL_CIPHER *cipher =
225 ssl3_choose_cipher(ssl, &client_hello, ssl_get_cipher_preferences(ssl));
226 if (cipher == NULL) {
227 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
228 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
229 return ssl_hs_error;
230 }
Steven Valdez143e8b32016-07-11 13:19:03 -0400231
Steven Valdez4aa154e2016-07-29 14:32:55 -0400232 ssl->s3->new_session->cipher = cipher;
233 ssl->s3->tmp.new_cipher = cipher;
234 } else {
235 uint16_t resumption_cipher;
236 if (!ssl_cipher_get_ecdhe_psk_cipher(ssl->s3->new_session->cipher,
237 &resumption_cipher)) {
238 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
239 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
240 return ssl_hs_error;
241 }
242 ssl->s3->tmp.new_cipher = SSL_get_cipher_by_value(resumption_cipher);
243 }
Steven Valdez143e8b32016-07-11 13:19:03 -0400244
David Benjamin613fe3b2016-07-22 17:39:29 +0200245 ssl->method->received_flight(ssl);
246
Steven Valdez143e8b32016-07-11 13:19:03 -0400247 /* The PRF hash is now known. Set up the key schedule and hash the
248 * ClientHello. */
Steven Valdez4aa154e2016-07-29 14:32:55 -0400249 size_t resumption_ctx_len =
Steven Valdez143e8b32016-07-11 13:19:03 -0400250 EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
Steven Valdez4aa154e2016-07-29 14:32:55 -0400251 if (ssl->s3->session_reused) {
252 uint8_t resumption_ctx[EVP_MAX_MD_SIZE];
253 if (!tls13_resumption_context(ssl, resumption_ctx, resumption_ctx_len,
254 ssl->s3->new_session) ||
255 !tls13_init_key_schedule(ssl, resumption_ctx, resumption_ctx_len)) {
256 return ssl_hs_error;
257 }
258 } else {
259 if (!tls13_init_key_schedule(ssl, kZeroes, resumption_ctx_len)) {
260 return ssl_hs_error;
261 }
Steven Valdez143e8b32016-07-11 13:19:03 -0400262 }
263
264 /* Resolve PSK and incorporate it into the secret. */
Steven Valdez5440fe02016-07-18 12:40:30 -0400265 if (!resolve_psk_secret(ssl)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400266 return ssl_hs_error;
267 }
268
269 /* Resolve ECDHE and incorporate it into the secret. */
Steven Valdez5440fe02016-07-18 12:40:30 -0400270 int need_retry;
David Benjamine14ff062016-08-09 16:21:24 -0400271 if (!resolve_ecdhe_secret(ssl, &need_retry, &client_hello)) {
Steven Valdez5440fe02016-07-18 12:40:30 -0400272 if (need_retry) {
273 hs->state = state_send_hello_retry_request;
274 return ssl_hs_ok;
Steven Valdez143e8b32016-07-11 13:19:03 -0400275 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400276 return ssl_hs_error;
277 }
Steven Valdez143e8b32016-07-11 13:19:03 -0400278
Steven Valdez5440fe02016-07-18 12:40:30 -0400279 hs->state = state_send_server_hello;
280 return ssl_hs_ok;
281}
Steven Valdez143e8b32016-07-11 13:19:03 -0400282
Steven Valdez5440fe02016-07-18 12:40:30 -0400283static enum ssl_hs_wait_t do_send_hello_retry_request(SSL *ssl,
284 SSL_HANDSHAKE *hs) {
285 CBB cbb, body, extensions;
286 uint16_t group_id;
287 if (!ssl->method->init_message(ssl, &cbb, &body,
288 SSL3_MT_HELLO_RETRY_REQUEST) ||
289 !CBB_add_u16(&body, ssl->version) ||
290 !CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
291 !tls1_get_shared_group(ssl, &group_id) ||
292 !CBB_add_u16(&body, group_id) ||
293 !CBB_add_u16_length_prefixed(&body, &extensions) ||
294 !ssl->method->finish_message(ssl, &cbb)) {
295 CBB_cleanup(&cbb);
296 return ssl_hs_error;
297 }
298
299 hs->state = state_flush_hello_retry_request;
300 return ssl_hs_write_message;
301}
302
303static enum ssl_hs_wait_t do_flush_hello_retry_request(SSL *ssl,
304 SSL_HANDSHAKE *hs) {
305 hs->state = state_process_second_client_hello;
306 return ssl_hs_flush_and_read_message;
307}
308
309static enum ssl_hs_wait_t do_process_second_client_hello(SSL *ssl,
310 SSL_HANDSHAKE *hs) {
311 if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
312 return ssl_hs_error;
313 }
314
David Benjamine14ff062016-08-09 16:21:24 -0400315 struct ssl_early_callback_ctx client_hello;
316 if (!ssl_early_callback_init(ssl, &client_hello, ssl->init_msg,
David Benjamind7573dc2016-07-20 19:05:22 +0200317 ssl->init_num)) {
Steven Valdez5440fe02016-07-18 12:40:30 -0400318 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
319 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
320 return ssl_hs_error;
321 }
322
323 int need_retry;
David Benjamine14ff062016-08-09 16:21:24 -0400324 if (!resolve_ecdhe_secret(ssl, &need_retry, &client_hello)) {
Steven Valdez5440fe02016-07-18 12:40:30 -0400325 if (need_retry) {
326 /* Only send one HelloRetryRequest. */
327 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
328 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
Steven Valdez143e8b32016-07-11 13:19:03 -0400329 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400330 return ssl_hs_error;
331 }
332
333 if (!ssl->method->hash_current_message(ssl)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400334 return ssl_hs_error;
335 }
336
David Benjamin613fe3b2016-07-22 17:39:29 +0200337 ssl->method->received_flight(ssl);
Steven Valdez143e8b32016-07-11 13:19:03 -0400338 hs->state = state_send_server_hello;
339 return ssl_hs_ok;
340}
341
342static enum ssl_hs_wait_t do_send_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
343 CBB cbb, body, extensions;
344 if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
345 !CBB_add_u16(&body, ssl->version) ||
346 !RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) ||
347 !CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
348 !CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
349 !CBB_add_u16_length_prefixed(&body, &extensions) ||
Steven Valdez4aa154e2016-07-29 14:32:55 -0400350 !ssl_ext_pre_shared_key_add_serverhello(ssl, &extensions) ||
Steven Valdez7259f2f2016-08-02 16:55:05 -0400351 !ssl_ext_key_share_add_serverhello(ssl, &extensions) ||
Steven Valdez143e8b32016-07-11 13:19:03 -0400352 !ssl->method->finish_message(ssl, &cbb)) {
353 CBB_cleanup(&cbb);
354 return ssl_hs_error;
355 }
356
357 hs->state = state_send_encrypted_extensions;
358 return ssl_hs_write_message;
359}
360
361static enum ssl_hs_wait_t do_send_encrypted_extensions(SSL *ssl,
362 SSL_HANDSHAKE *hs) {
363 if (!tls13_set_handshake_traffic(ssl)) {
364 return ssl_hs_error;
365 }
366
367 CBB cbb, body;
368 if (!ssl->method->init_message(ssl, &cbb, &body,
369 SSL3_MT_ENCRYPTED_EXTENSIONS) ||
370 !ssl_add_serverhello_tlsext(ssl, &body) ||
371 !ssl->method->finish_message(ssl, &cbb)) {
372 CBB_cleanup(&cbb);
373 return ssl_hs_error;
374 }
375
376 hs->state = state_send_certificate_request;
377 return ssl_hs_write_message;
378}
379
380static enum ssl_hs_wait_t do_send_certificate_request(SSL *ssl,
381 SSL_HANDSHAKE *hs) {
382 /* Determine whether to request a client certificate. */
383 ssl->s3->tmp.cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
384 /* CertificateRequest may only be sent in certificate-based ciphers. */
385 if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
386 ssl->s3->tmp.cert_request = 0;
387 }
388
389 if (!ssl->s3->tmp.cert_request) {
390 /* Skip this state. */
391 hs->state = state_send_server_certificate;
392 return ssl_hs_ok;
393 }
394
395 CBB cbb, body, sigalgs_cbb;
396 if (!ssl->method->init_message(ssl, &cbb, &body,
397 SSL3_MT_CERTIFICATE_REQUEST) ||
398 !CBB_add_u8(&body, 0 /* no certificate_request_context. */)) {
399 goto err;
400 }
401
402 const uint16_t *sigalgs;
403 size_t sigalgs_len = tls12_get_psigalgs(ssl, &sigalgs);
404 if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) {
405 goto err;
406 }
407
408 for (size_t i = 0; i < sigalgs_len; i++) {
409 if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) {
410 goto err;
411 }
412 }
413
414 if (!ssl_add_client_CA_list(ssl, &body) ||
415 !CBB_add_u16(&body, 0 /* empty certificate_extensions. */) ||
416 !ssl->method->finish_message(ssl, &cbb)) {
417 goto err;
418 }
419
420 hs->state = state_send_server_certificate;
421 return ssl_hs_write_message;
422
423err:
424 CBB_cleanup(&cbb);
425 return ssl_hs_error;
426}
427
428static enum ssl_hs_wait_t do_send_server_certificate(SSL *ssl,
429 SSL_HANDSHAKE *hs) {
430 if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
431 hs->state = state_send_server_finished;
432 return ssl_hs_ok;
433 }
434
435 if (!ssl_has_certificate(ssl)) {
436 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
437 return ssl_hs_error;
438 }
439
440 if (!tls13_prepare_certificate(ssl)) {
441 return ssl_hs_error;
442 }
443
444 hs->state = state_send_server_certificate_verify;
445 return ssl_hs_write_message;
446}
447
448static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL *ssl,
449 SSL_HANDSHAKE *hs,
450 int is_first_run) {
451 switch (tls13_prepare_certificate_verify(ssl, is_first_run)) {
452 case ssl_private_key_success:
453 hs->state = state_send_server_finished;
454 return ssl_hs_write_message;
455
456 case ssl_private_key_retry:
457 hs->state = state_complete_server_certificate_verify;
458 return ssl_hs_private_key_operation;
459
460 case ssl_private_key_failure:
461 return ssl_hs_error;
462 }
463
464 assert(0);
465 return ssl_hs_error;
466}
467
468static enum ssl_hs_wait_t do_send_server_finished(SSL *ssl, SSL_HANDSHAKE *hs) {
469 if (!tls13_prepare_finished(ssl)) {
470 return ssl_hs_error;
471 }
472
473 hs->state = state_flush;
474 return ssl_hs_write_message;
475}
476
477static enum ssl_hs_wait_t do_flush(SSL *ssl, SSL_HANDSHAKE *hs) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400478 /* Update the secret to the master secret and derive traffic keys. */
Steven Valdez143e8b32016-07-11 13:19:03 -0400479 if (!tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len) ||
480 !tls13_derive_traffic_secret_0(ssl) ||
481 !tls13_set_traffic_key(ssl, type_data, evp_aead_seal,
482 hs->traffic_secret_0, hs->hash_len)) {
483 return ssl_hs_error;
484 }
485
486 hs->state = state_process_client_certificate;
David Benjaminf2401eb2016-07-18 22:25:05 +0200487 return ssl_hs_flush_and_read_message;
Steven Valdez143e8b32016-07-11 13:19:03 -0400488}
489
490static enum ssl_hs_wait_t do_process_client_certificate(SSL *ssl,
491 SSL_HANDSHAKE *hs) {
492 if (!ssl->s3->tmp.cert_request) {
493 /* Skip this state. */
Steven Valdez4aa154e2016-07-29 14:32:55 -0400494 hs->state = state_process_client_finished;
Steven Valdez143e8b32016-07-11 13:19:03 -0400495 return ssl_hs_ok;
496 }
497
David Benjamin4087df92016-08-01 20:16:31 -0400498 const int allow_anonymous =
499 (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) == 0;
500
Steven Valdez143e8b32016-07-11 13:19:03 -0400501 if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
David Benjamin4087df92016-08-01 20:16:31 -0400502 !tls13_process_certificate(ssl, allow_anonymous) ||
Steven Valdez143e8b32016-07-11 13:19:03 -0400503 !ssl->method->hash_current_message(ssl)) {
504 return ssl_hs_error;
505 }
506
David Benjamin3ce43892016-08-01 19:41:34 -0400507 /* For historical reasons, the server's copy of the chain does not include the
508 * leaf while the client's does. */
509 if (sk_X509_num(ssl->s3->new_session->cert_chain) > 0) {
510 X509_free(sk_X509_shift(ssl->s3->new_session->cert_chain));
511 }
512
Steven Valdez143e8b32016-07-11 13:19:03 -0400513 hs->state = state_process_client_certificate_verify;
514 return ssl_hs_read_message;
515}
516
517static enum ssl_hs_wait_t do_process_client_certificate_verify(
518 SSL *ssl, SSL_HANDSHAKE *hs) {
Steven Valdez87eab492016-06-27 16:34:59 -0400519 if (ssl->s3->new_session->peer == NULL) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400520 /* Skip this state. */
521 hs->state = state_process_client_finished;
522 return ssl_hs_ok;
523 }
524
525 if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
526 !tls13_process_certificate_verify(ssl) ||
527 !ssl->method->hash_current_message(ssl)) {
528 return 0;
529 }
530
531 hs->state = state_process_client_finished;
532 return ssl_hs_read_message;
533}
534
535static enum ssl_hs_wait_t do_process_client_finished(SSL *ssl,
536 SSL_HANDSHAKE *hs) {
537 if (!tls13_check_message_type(ssl, SSL3_MT_FINISHED) ||
538 !tls13_process_finished(ssl) ||
539 !ssl->method->hash_current_message(ssl) ||
540 /* evp_aead_seal keys have already been switched. */
541 !tls13_set_traffic_key(ssl, type_data, evp_aead_open,
542 hs->traffic_secret_0, hs->hash_len) ||
543 !tls13_finalize_keys(ssl)) {
544 return ssl_hs_error;
545 }
546
David Benjamin613fe3b2016-07-22 17:39:29 +0200547 ssl->method->received_flight(ssl);
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400548 hs->state = state_send_new_session_ticket;
Steven Valdez143e8b32016-07-11 13:19:03 -0400549 return ssl_hs_ok;
550}
551
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400552static enum ssl_hs_wait_t do_send_new_session_ticket(SSL *ssl,
553 SSL_HANDSHAKE *hs) {
554 SSL_SESSION *session = ssl->s3->new_session;
Martin Kreichgauerbaafa4a2016-08-09 10:18:40 -0700555 session->tlsext_tick_lifetime_hint = session->timeout;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400556 session->ticket_flags = SSL_TICKET_ALLOW_DHE_RESUMPTION;
557 if (!RAND_bytes((uint8_t *)&session->ticket_age_add,
558 sizeof(session->ticket_age_add))) {
559 return 0;
560 }
561 session->ticket_age_add_valid = 1;
562
563 CBB cbb, body, ticket;
564 if (!ssl->method->init_message(ssl, &cbb, &body,
565 SSL3_MT_NEW_SESSION_TICKET) ||
Martin Kreichgauerbaafa4a2016-08-09 10:18:40 -0700566 !CBB_add_u32(&body, session->tlsext_tick_lifetime_hint) ||
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400567 !CBB_add_u32(&body, session->ticket_flags) ||
568 !CBB_add_u32(&body, session->ticket_age_add) ||
569 !CBB_add_u16(&body, 0 /* no ticket extensions */) ||
570 !CBB_add_u16_length_prefixed(&body, &ticket) ||
571 !ssl_encrypt_ticket(ssl, &ticket, session) ||
572 !ssl->method->finish_message(ssl, &cbb)) {
573 CBB_cleanup(&cbb);
574 return ssl_hs_error;
575 }
576
577 hs->session_tickets_sent++;
578
579 hs->state = state_flush_new_session_ticket;
580 return ssl_hs_write_message;
581}
582
583/* TLS 1.3 recommends single-use tickets, so issue multiple tickets in case the
584 * client makes several connections before getting a renewal. */
585static const int kNumTickets = 2;
586
587static enum ssl_hs_wait_t do_flush_new_session_ticket(SSL *ssl,
588 SSL_HANDSHAKE *hs) {
589 if (hs->session_tickets_sent >= kNumTickets) {
590 hs->state = state_done;
591 } else {
592 hs->state = state_send_new_session_ticket;
593 }
594 return ssl_hs_flush;
595}
596
Steven Valdez143e8b32016-07-11 13:19:03 -0400597enum ssl_hs_wait_t tls13_server_handshake(SSL *ssl) {
598 SSL_HANDSHAKE *hs = ssl->s3->hs;
599
600 while (hs->state != state_done) {
601 enum ssl_hs_wait_t ret = ssl_hs_error;
602 enum server_hs_state_t state = hs->state;
603 switch (state) {
604 case state_process_client_hello:
605 ret = do_process_client_hello(ssl, hs);
606 break;
David Benjamin25fe85b2016-08-09 20:00:32 -0400607 case state_select_parameters:
608 ret = do_select_parameters(ssl, hs);
609 break;
Steven Valdez5440fe02016-07-18 12:40:30 -0400610 case state_send_hello_retry_request:
611 ret = do_send_hello_retry_request(ssl, hs);
612 break;
613 case state_flush_hello_retry_request:
614 ret = do_flush_hello_retry_request(ssl, hs);
615 break;
616 case state_process_second_client_hello:
617 ret = do_process_second_client_hello(ssl, hs);
618 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400619 case state_send_server_hello:
620 ret = do_send_server_hello(ssl, hs);
621 break;
622 case state_send_encrypted_extensions:
623 ret = do_send_encrypted_extensions(ssl, hs);
624 break;
625 case state_send_certificate_request:
626 ret = do_send_certificate_request(ssl, hs);
627 break;
628 case state_send_server_certificate:
629 ret = do_send_server_certificate(ssl, hs);
630 break;
631 case state_send_server_certificate_verify:
632 ret = do_send_server_certificate_verify(ssl, hs, 1 /* first run */);
633 break;
634 case state_complete_server_certificate_verify:
635 ret = do_send_server_certificate_verify(ssl, hs, 0 /* complete */);
636 break;
637 case state_send_server_finished:
638 ret = do_send_server_finished(ssl, hs);
639 break;
640 case state_flush:
641 ret = do_flush(ssl, hs);
642 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400643 case state_process_client_certificate:
644 ret = do_process_client_certificate(ssl, hs);
645 break;
646 case state_process_client_certificate_verify:
647 ret = do_process_client_certificate_verify(ssl, hs);
648 break;
649 case state_process_client_finished:
650 ret = do_process_client_finished(ssl, hs);
651 break;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400652 case state_send_new_session_ticket:
653 ret = do_send_new_session_ticket(ssl, hs);
654 break;
655 case state_flush_new_session_ticket:
656 ret = do_flush_new_session_ticket(ssl, hs);
657 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400658 case state_done:
659 ret = ssl_hs_ok;
660 break;
661 }
662
663 if (ret != ssl_hs_ok) {
664 return ret;
665 }
666 }
667
668 return ssl_hs_ok;
669}