blob: 7181f4652078241fba7b1b21f46bfb65bbb1d08a [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
David Benjaminabbbee12016-10-31 19:20:42 -040020#include <openssl/aead.h>
Steven Valdez143e8b32016-07-11 13:19:03 -040021#include <openssl/bytestring.h>
22#include <openssl/digest.h>
23#include <openssl/err.h>
24#include <openssl/mem.h>
25#include <openssl/rand.h>
26#include <openssl/stack.h>
27
28#include "internal.h"
29
30
31enum server_hs_state_t {
32 state_process_client_hello = 0,
David Benjamin25fe85b2016-08-09 20:00:32 -040033 state_select_parameters,
Steven Valdez5440fe02016-07-18 12:40:30 -040034 state_send_hello_retry_request,
35 state_flush_hello_retry_request,
36 state_process_second_client_hello,
Steven Valdez143e8b32016-07-11 13:19:03 -040037 state_send_server_hello,
38 state_send_encrypted_extensions,
39 state_send_certificate_request,
40 state_send_server_certificate,
41 state_send_server_certificate_verify,
42 state_complete_server_certificate_verify,
43 state_send_server_finished,
44 state_flush,
Steven Valdez143e8b32016-07-11 13:19:03 -040045 state_process_client_certificate,
46 state_process_client_certificate_verify,
Nick Harper60a85cb2016-09-23 16:25:11 -070047 state_process_channel_id,
Steven Valdez143e8b32016-07-11 13:19:03 -040048 state_process_client_finished,
Steven Valdez1e6f11a2016-07-27 11:10:52 -040049 state_send_new_session_ticket,
David Benjamin0a011fc2016-11-03 17:19:16 -040050 state_flush_new_session_tickets,
Steven Valdez143e8b32016-07-11 13:19:03 -040051 state_done,
52};
53
Steven Valdez5440fe02016-07-18 12:40:30 -040054static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
55
David Benjamin6e4fc332016-11-17 16:43:08 +090056static int resolve_ecdhe_secret(SSL_HANDSHAKE *hs, int *out_need_retry,
David Benjamin731058e2016-12-03 23:15:13 -050057 SSL_CLIENT_HELLO *client_hello) {
David Benjamin6e4fc332016-11-17 16:43:08 +090058 SSL *const ssl = hs->ssl;
Steven Valdez5440fe02016-07-18 12:40:30 -040059 *out_need_retry = 0;
Steven Valdez5440fe02016-07-18 12:40:30 -040060
Steven Valdez803c77a2016-09-06 14:13:43 -040061 /* We only support connections that include an ECDHE key exchange. */
Steven Valdez5440fe02016-07-18 12:40:30 -040062 CBS key_share;
David Benjamin731058e2016-12-03 23:15:13 -050063 if (!ssl_client_hello_get_extension(client_hello, &key_share,
64 TLSEXT_TYPE_key_share)) {
Steven Valdez5440fe02016-07-18 12:40:30 -040065 OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
66 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
David Benjamin6929f272016-11-16 19:10:08 +090067 return 0;
Steven Valdez5440fe02016-07-18 12:40:30 -040068 }
69
Steven Valdez5440fe02016-07-18 12:40:30 -040070 int found_key_share;
71 uint8_t *dhe_secret;
72 size_t dhe_secret_len;
David Benjamin7e1f9842016-09-20 19:24:40 -040073 uint8_t alert = SSL_AD_DECODE_ERROR;
David Benjamin8baf9632016-11-17 17:11:16 +090074 if (!ssl_ext_key_share_parse_clienthello(hs, &found_key_share, &dhe_secret,
Steven Valdez7259f2f2016-08-02 16:55:05 -040075 &dhe_secret_len, &alert,
76 &key_share)) {
Steven Valdez5440fe02016-07-18 12:40:30 -040077 ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
78 return 0;
79 }
80
81 if (!found_key_share) {
82 *out_need_retry = 1;
83 return 0;
84 }
85
David Benjamin6e4fc332016-11-17 16:43:08 +090086 int ok = tls13_advance_key_schedule(hs, dhe_secret, dhe_secret_len);
Steven Valdez5440fe02016-07-18 12:40:30 -040087 OPENSSL_free(dhe_secret);
88 return ok;
89}
90
David Benjaminc3c88822016-11-14 10:32:04 +090091static enum ssl_hs_wait_t do_process_client_hello(SSL_HANDSHAKE *hs) {
92 SSL *const ssl = hs->ssl;
Steven Valdez143e8b32016-07-11 13:19:03 -040093 if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
94 return ssl_hs_error;
95 }
96
David Benjamin731058e2016-12-03 23:15:13 -050097 SSL_CLIENT_HELLO client_hello;
98 if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
99 ssl->init_num)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400100 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
101 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
102 return ssl_hs_error;
103 }
104
Steven Valdez143e8b32016-07-11 13:19:03 -0400105 assert(ssl->s3->have_version);
106
107 /* Load the client random. */
David Benjamine14ff062016-08-09 16:21:24 -0400108 if (client_hello.random_len != SSL3_RANDOM_SIZE) {
109 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin6929f272016-11-16 19:10:08 +0900110 return ssl_hs_error;
David Benjamine14ff062016-08-09 16:21:24 -0400111 }
112 memcpy(ssl->s3->client_random, client_hello.random, client_hello.random_len);
Steven Valdez143e8b32016-07-11 13:19:03 -0400113
David Benjamin4eb95cc2016-11-16 17:08:23 +0900114 /* TLS 1.3 requires the peer only advertise the null compression. */
115 if (client_hello.compression_methods_len != 1 ||
116 client_hello.compression_methods[0] != 0) {
117 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMPRESSION_LIST);
118 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
David Benjamin6929f272016-11-16 19:10:08 +0900119 return ssl_hs_error;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400120 }
121
David Benjamin4eb95cc2016-11-16 17:08:23 +0900122 /* TLS extensions. */
David Benjamin8c880a22016-12-03 02:20:34 -0500123 if (!ssl_parse_clienthello_tlsext(hs, &client_hello)) {
David Benjamin4eb95cc2016-11-16 17:08:23 +0900124 OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
125 return ssl_hs_error;
126 }
Steven Valdeza833c352016-11-01 13:39:36 -0400127
David Benjamin3977f302016-12-11 13:30:41 -0500128 hs->tls13_state = state_select_parameters;
David Benjamin34202b92016-11-16 19:07:53 +0900129 return ssl_hs_ok;
130}
131
132static const SSL_CIPHER *choose_tls13_cipher(
David Benjamin731058e2016-12-03 23:15:13 -0500133 const SSL *ssl, const SSL_CLIENT_HELLO *client_hello) {
David Benjamin34202b92016-11-16 19:07:53 +0900134 if (client_hello->cipher_suites_len % 2 != 0) {
135 return NULL;
136 }
137
138 CBS cipher_suites;
139 CBS_init(&cipher_suites, client_hello->cipher_suites,
140 client_hello->cipher_suites_len);
141
142 const int aes_is_fine = EVP_has_aes_hardware();
David Benjaminf01f42a2016-11-16 19:05:33 +0900143 const uint16_t version = ssl3_protocol_version(ssl);
David Benjamin34202b92016-11-16 19:07:53 +0900144
145 const SSL_CIPHER *best = NULL;
146 while (CBS_len(&cipher_suites) > 0) {
147 uint16_t cipher_suite;
148 if (!CBS_get_u16(&cipher_suites, &cipher_suite)) {
149 return NULL;
150 }
151
David Benjaminf01f42a2016-11-16 19:05:33 +0900152 /* Limit to TLS 1.3 ciphers we know about. */
David Benjamin34202b92016-11-16 19:07:53 +0900153 const SSL_CIPHER *candidate = SSL_get_cipher_by_value(cipher_suite);
David Benjaminf01f42a2016-11-16 19:05:33 +0900154 if (candidate == NULL ||
155 SSL_CIPHER_get_min_version(candidate) > version ||
156 SSL_CIPHER_get_max_version(candidate) < version) {
David Benjamin34202b92016-11-16 19:07:53 +0900157 continue;
158 }
159
160 /* TLS 1.3 removes legacy ciphers, so honor the client order, but prefer
161 * ChaCha20 if we do not have AES hardware. */
162 if (aes_is_fine) {
163 return candidate;
164 }
165
166 if (candidate->algorithm_enc == SSL_CHACHA20POLY1305) {
167 return candidate;
168 }
169
170 if (best == NULL) {
171 best = candidate;
172 }
173 }
174
175 return best;
176}
177
David Benjaminc3c88822016-11-14 10:32:04 +0900178static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
179 SSL *const ssl = hs->ssl;
David Benjamin34202b92016-11-16 19:07:53 +0900180 /* Call |cert_cb| to update server certificates if required. */
181 if (ssl->cert->cert_cb != NULL) {
182 int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
183 if (rv == 0) {
184 OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
185 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
186 return ssl_hs_error;
187 }
188 if (rv < 0) {
David Benjamin3977f302016-12-11 13:30:41 -0500189 hs->tls13_state = state_select_parameters;
David Benjamin34202b92016-11-16 19:07:53 +0900190 return ssl_hs_x509_lookup;
191 }
192 }
193
David Benjamin731058e2016-12-03 23:15:13 -0500194 SSL_CLIENT_HELLO client_hello;
195 if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
196 ssl->init_num)) {
David Benjamin34202b92016-11-16 19:07:53 +0900197 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
198 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
199 return ssl_hs_error;
200 }
201
David Benjaminf01f42a2016-11-16 19:05:33 +0900202 /* Negotiate the cipher suite. */
203 ssl->s3->tmp.new_cipher = choose_tls13_cipher(ssl, &client_hello);
204 if (ssl->s3->tmp.new_cipher == NULL) {
205 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
206 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
207 return ssl_hs_error;
208 }
209
210 /* Decode the ticket if we agree on a PSK key exchange mode. */
David Benjamin4eb95cc2016-11-16 17:08:23 +0900211 uint8_t alert = SSL_AD_DECODE_ERROR;
212 SSL_SESSION *session = NULL;
213 CBS pre_shared_key, binders;
214 if (hs->accept_psk_mode &&
David Benjamin731058e2016-12-03 23:15:13 -0500215 ssl_client_hello_get_extension(&client_hello, &pre_shared_key,
216 TLSEXT_TYPE_pre_shared_key)) {
David Benjamin4eb95cc2016-11-16 17:08:23 +0900217 /* Verify that the pre_shared_key extension is the last extension in
218 * ClientHello. */
219 if (CBS_data(&pre_shared_key) + CBS_len(&pre_shared_key) !=
220 client_hello.extensions + client_hello.extensions_len) {
221 OPENSSL_PUT_ERROR(SSL, SSL_R_PRE_SHARED_KEY_MUST_BE_LAST);
222 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
223 return ssl_hs_error;
224 }
225
David Benjamin8baf9632016-11-17 17:11:16 +0900226 if (!ssl_ext_pre_shared_key_parse_clienthello(hs, &session, &binders,
David Benjamin4eb95cc2016-11-16 17:08:23 +0900227 &alert, &pre_shared_key)) {
228 ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
229 return ssl_hs_error;
Steven Valdeza833c352016-11-01 13:39:36 -0400230 }
231 }
232
Steven Valdez4aa154e2016-07-29 14:32:55 -0400233 if (session != NULL &&
David Benjamin75f99142016-11-12 12:36:06 +0900234 !ssl_session_is_resumable(ssl, session)) {
Steven Valdez4aa154e2016-07-29 14:32:55 -0400235 SSL_SESSION_free(session);
236 session = NULL;
237 }
238
David Benjaminf01f42a2016-11-16 19:05:33 +0900239 /* Set up the new session, either using the original one as a template or
240 * creating a fresh one. */
Steven Valdez4aa154e2016-07-29 14:32:55 -0400241 if (session == NULL) {
David Benjaminf3c8f8d2016-11-17 17:20:47 +0900242 if (!ssl_get_new_session(hs, 1 /* server */)) {
Steven Valdez4aa154e2016-07-29 14:32:55 -0400243 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
244 return ssl_hs_error;
245 }
David Benjaminf01f42a2016-11-16 19:05:33 +0900246
247 ssl->s3->new_session->cipher = ssl->s3->tmp.new_cipher;
248
249 /* On new sessions, stash the SNI value in the session. */
David Benjamin6e4fc332016-11-17 16:43:08 +0900250 if (hs->hostname != NULL) {
251 ssl->s3->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
David Benjaminf01f42a2016-11-16 19:05:33 +0900252 if (ssl->s3->new_session->tlsext_hostname == NULL) {
253 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
254 return ssl_hs_error;
255 }
256 }
Steven Valdez4aa154e2016-07-29 14:32:55 -0400257 } else {
Steven Valdeza833c352016-11-01 13:39:36 -0400258 /* Check the PSK binder. */
259 if (!tls13_verify_psk_binder(ssl, session, &binders)) {
260 SSL_SESSION_free(session);
261 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
262 return ssl_hs_error;
263 }
264
Steven Valdez4aa154e2016-07-29 14:32:55 -0400265 /* Only authentication information carries over in TLS 1.3. */
266 ssl->s3->new_session = SSL_SESSION_dup(session, SSL_SESSION_DUP_AUTH_ONLY);
267 if (ssl->s3->new_session == NULL) {
268 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
269 return ssl_hs_error;
270 }
271 ssl->s3->session_reused = 1;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400272 SSL_SESSION_free(session);
Steven Valdez143e8b32016-07-11 13:19:03 -0400273 }
274
275 if (ssl->ctx->dos_protection_cb != NULL &&
David Benjamine14ff062016-08-09 16:21:24 -0400276 ssl->ctx->dos_protection_cb(&client_hello) == 0) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400277 /* Connection rejected for DOS reasons. */
278 OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
David Benjamin2c66e072016-09-16 15:58:00 -0400279 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
Steven Valdez143e8b32016-07-11 13:19:03 -0400280 return ssl_hs_error;
281 }
282
David Benjaminf01f42a2016-11-16 19:05:33 +0900283 /* HTTP/2 negotiation depends on the cipher suite, so ALPN negotiation was
284 * deferred. Complete it now. */
David Benjaminf3c8f8d2016-11-17 17:20:47 +0900285 if (!ssl_negotiate_alpn(hs, &alert, &client_hello)) {
David Benjamin9ef31f02016-10-31 18:01:13 -0400286 ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
287 return ssl_hs_error;
288 }
Steven Valdez803c77a2016-09-06 14:13:43 -0400289
David Benjamin8f820b42016-11-30 11:24:40 -0500290 /* The PRF hash is now known. Set up the key schedule. */
Steven Valdez803c77a2016-09-06 14:13:43 -0400291 size_t hash_len =
Steven Valdez143e8b32016-07-11 13:19:03 -0400292 EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
David Benjamin6e4fc332016-11-17 16:43:08 +0900293 if (!tls13_init_key_schedule(hs)) {
David Benjamin8f820b42016-11-30 11:24:40 -0500294 return ssl_hs_error;
Steven Valdez143e8b32016-07-11 13:19:03 -0400295 }
296
David Benjamin8f820b42016-11-30 11:24:40 -0500297 /* Incorporate the PSK into the running secret. */
298 if (ssl->s3->session_reused) {
David Benjamin6e4fc332016-11-17 16:43:08 +0900299 if (!tls13_advance_key_schedule(hs, ssl->s3->new_session->master_key,
David Benjamin8f820b42016-11-30 11:24:40 -0500300 ssl->s3->new_session->master_key_length)) {
301 return ssl_hs_error;
302 }
David Benjamin6e4fc332016-11-17 16:43:08 +0900303 } else if (!tls13_advance_key_schedule(hs, kZeroes, hash_len)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400304 return ssl_hs_error;
305 }
306
David Benjaminf01f42a2016-11-16 19:05:33 +0900307 ssl->method->received_flight(ssl);
308
Steven Valdez143e8b32016-07-11 13:19:03 -0400309 /* Resolve ECDHE and incorporate it into the secret. */
Steven Valdez5440fe02016-07-18 12:40:30 -0400310 int need_retry;
David Benjamin6e4fc332016-11-17 16:43:08 +0900311 if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) {
Steven Valdez5440fe02016-07-18 12:40:30 -0400312 if (need_retry) {
David Benjamin3977f302016-12-11 13:30:41 -0500313 hs->tls13_state = state_send_hello_retry_request;
Steven Valdez5440fe02016-07-18 12:40:30 -0400314 return ssl_hs_ok;
Steven Valdez143e8b32016-07-11 13:19:03 -0400315 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400316 return ssl_hs_error;
317 }
Steven Valdez143e8b32016-07-11 13:19:03 -0400318
David Benjamin3977f302016-12-11 13:30:41 -0500319 hs->tls13_state = state_send_server_hello;
Steven Valdez5440fe02016-07-18 12:40:30 -0400320 return ssl_hs_ok;
321}
Steven Valdez143e8b32016-07-11 13:19:03 -0400322
David Benjaminc3c88822016-11-14 10:32:04 +0900323static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) {
324 SSL *const ssl = hs->ssl;
Steven Valdez5440fe02016-07-18 12:40:30 -0400325 CBB cbb, body, extensions;
326 uint16_t group_id;
327 if (!ssl->method->init_message(ssl, &cbb, &body,
328 SSL3_MT_HELLO_RETRY_REQUEST) ||
329 !CBB_add_u16(&body, ssl->version) ||
David Benjaminf3c8f8d2016-11-17 17:20:47 +0900330 !tls1_get_shared_group(hs, &group_id) ||
Steven Valdez5440fe02016-07-18 12:40:30 -0400331 !CBB_add_u16_length_prefixed(&body, &extensions) ||
David Benjamin3baa6e12016-10-07 21:10:38 -0400332 !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
333 !CBB_add_u16(&extensions, 2 /* length */) ||
334 !CBB_add_u16(&extensions, group_id) ||
Steven Valdez5eead162016-11-11 22:23:25 -0500335 !ssl_complete_message(ssl, &cbb)) {
Steven Valdez5440fe02016-07-18 12:40:30 -0400336 CBB_cleanup(&cbb);
337 return ssl_hs_error;
338 }
339
David Benjamin3977f302016-12-11 13:30:41 -0500340 hs->tls13_state = state_flush_hello_retry_request;
Steven Valdez5440fe02016-07-18 12:40:30 -0400341 return ssl_hs_write_message;
342}
343
David Benjaminc3c88822016-11-14 10:32:04 +0900344static enum ssl_hs_wait_t do_flush_hello_retry_request(SSL_HANDSHAKE *hs) {
David Benjamin3977f302016-12-11 13:30:41 -0500345 hs->tls13_state = state_process_second_client_hello;
Steven Valdez5440fe02016-07-18 12:40:30 -0400346 return ssl_hs_flush_and_read_message;
347}
348
David Benjaminc3c88822016-11-14 10:32:04 +0900349static enum ssl_hs_wait_t do_process_second_client_hello(SSL_HANDSHAKE *hs) {
350 SSL *const ssl = hs->ssl;
Steven Valdez5440fe02016-07-18 12:40:30 -0400351 if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
352 return ssl_hs_error;
353 }
354
David Benjamin731058e2016-12-03 23:15:13 -0500355 SSL_CLIENT_HELLO client_hello;
356 if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
357 ssl->init_num)) {
Steven Valdez5440fe02016-07-18 12:40:30 -0400358 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
359 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
360 return ssl_hs_error;
361 }
362
363 int need_retry;
David Benjamin6e4fc332016-11-17 16:43:08 +0900364 if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) {
Steven Valdez5440fe02016-07-18 12:40:30 -0400365 if (need_retry) {
366 /* Only send one HelloRetryRequest. */
367 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
368 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
Steven Valdez143e8b32016-07-11 13:19:03 -0400369 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400370 return ssl_hs_error;
371 }
372
David Benjaminced94792016-11-14 17:12:11 +0900373 if (!ssl_hash_current_message(ssl)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400374 return ssl_hs_error;
375 }
376
David Benjamin613fe3b2016-07-22 17:39:29 +0200377 ssl->method->received_flight(ssl);
David Benjamin3977f302016-12-11 13:30:41 -0500378 hs->tls13_state = state_send_server_hello;
Steven Valdez143e8b32016-07-11 13:19:03 -0400379 return ssl_hs_ok;
380}
381
David Benjaminc3c88822016-11-14 10:32:04 +0900382static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
383 SSL *const ssl = hs->ssl;
Steven Valdez143e8b32016-07-11 13:19:03 -0400384 CBB cbb, body, extensions;
385 if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
386 !CBB_add_u16(&body, ssl->version) ||
387 !RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) ||
388 !CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
389 !CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
390 !CBB_add_u16_length_prefixed(&body, &extensions) ||
David Benjamin8baf9632016-11-17 17:11:16 +0900391 !ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) ||
392 !ssl_ext_key_share_add_serverhello(hs, &extensions) ||
Steven Valdeza833c352016-11-01 13:39:36 -0400393 !ssl_complete_message(ssl, &cbb)) {
Steven Valdez803c77a2016-09-06 14:13:43 -0400394 goto err;
Steven Valdez143e8b32016-07-11 13:19:03 -0400395 }
396
David Benjamin3977f302016-12-11 13:30:41 -0500397 hs->tls13_state = state_send_encrypted_extensions;
Steven Valdez143e8b32016-07-11 13:19:03 -0400398 return ssl_hs_write_message;
Steven Valdez803c77a2016-09-06 14:13:43 -0400399
400err:
401 CBB_cleanup(&cbb);
402 return ssl_hs_error;
Steven Valdez143e8b32016-07-11 13:19:03 -0400403}
404
David Benjaminc3c88822016-11-14 10:32:04 +0900405static enum ssl_hs_wait_t do_send_encrypted_extensions(SSL_HANDSHAKE *hs) {
406 SSL *const ssl = hs->ssl;
Steven Valdez4cb84942016-12-16 11:29:28 -0500407 if (!tls13_derive_handshake_secrets(hs) ||
408 !tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret,
409 hs->hash_len) ||
410 !tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_handshake_secret,
411 hs->hash_len)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400412 return ssl_hs_error;
413 }
414
415 CBB cbb, body;
416 if (!ssl->method->init_message(ssl, &cbb, &body,
417 SSL3_MT_ENCRYPTED_EXTENSIONS) ||
David Benjamin8c880a22016-12-03 02:20:34 -0500418 !ssl_add_serverhello_tlsext(hs, &body) ||
Steven Valdez5eead162016-11-11 22:23:25 -0500419 !ssl_complete_message(ssl, &cbb)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400420 CBB_cleanup(&cbb);
421 return ssl_hs_error;
422 }
423
David Benjamin3977f302016-12-11 13:30:41 -0500424 hs->tls13_state = state_send_certificate_request;
Steven Valdez143e8b32016-07-11 13:19:03 -0400425 return ssl_hs_write_message;
426}
427
David Benjaminc3c88822016-11-14 10:32:04 +0900428static enum ssl_hs_wait_t do_send_certificate_request(SSL_HANDSHAKE *hs) {
429 SSL *const ssl = hs->ssl;
Steven Valdez143e8b32016-07-11 13:19:03 -0400430 /* Determine whether to request a client certificate. */
David Benjaminc3c88822016-11-14 10:32:04 +0900431 hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
Steven Valdez803c77a2016-09-06 14:13:43 -0400432 /* CertificateRequest may only be sent in non-resumption handshakes. */
433 if (ssl->s3->session_reused) {
David Benjaminc3c88822016-11-14 10:32:04 +0900434 hs->cert_request = 0;
Steven Valdez143e8b32016-07-11 13:19:03 -0400435 }
436
David Benjaminc3c88822016-11-14 10:32:04 +0900437 if (!hs->cert_request) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400438 /* Skip this state. */
David Benjamin3977f302016-12-11 13:30:41 -0500439 hs->tls13_state = state_send_server_certificate;
Steven Valdez143e8b32016-07-11 13:19:03 -0400440 return ssl_hs_ok;
441 }
442
443 CBB cbb, body, sigalgs_cbb;
444 if (!ssl->method->init_message(ssl, &cbb, &body,
445 SSL3_MT_CERTIFICATE_REQUEST) ||
446 !CBB_add_u8(&body, 0 /* no certificate_request_context. */)) {
447 goto err;
448 }
449
450 const uint16_t *sigalgs;
David Benjamin3ef76972016-10-17 17:59:54 -0400451 size_t num_sigalgs = tls12_get_verify_sigalgs(ssl, &sigalgs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400452 if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) {
453 goto err;
454 }
455
David Benjamin0fc37ef2016-08-17 15:29:46 -0400456 for (size_t i = 0; i < num_sigalgs; i++) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400457 if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) {
458 goto err;
459 }
460 }
461
462 if (!ssl_add_client_CA_list(ssl, &body) ||
463 !CBB_add_u16(&body, 0 /* empty certificate_extensions. */) ||
Steven Valdez5eead162016-11-11 22:23:25 -0500464 !ssl_complete_message(ssl, &cbb)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400465 goto err;
466 }
467
David Benjamin3977f302016-12-11 13:30:41 -0500468 hs->tls13_state = state_send_server_certificate;
Steven Valdez143e8b32016-07-11 13:19:03 -0400469 return ssl_hs_write_message;
470
471err:
472 CBB_cleanup(&cbb);
473 return ssl_hs_error;
474}
475
David Benjaminc3c88822016-11-14 10:32:04 +0900476static enum ssl_hs_wait_t do_send_server_certificate(SSL_HANDSHAKE *hs) {
477 SSL *const ssl = hs->ssl;
Steven Valdez803c77a2016-09-06 14:13:43 -0400478 if (ssl->s3->session_reused) {
David Benjamin3977f302016-12-11 13:30:41 -0500479 hs->tls13_state = state_send_server_finished;
Steven Valdez143e8b32016-07-11 13:19:03 -0400480 return ssl_hs_ok;
481 }
482
483 if (!ssl_has_certificate(ssl)) {
484 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
485 return ssl_hs_error;
486 }
487
David Benjamin6e4fc332016-11-17 16:43:08 +0900488 if (!tls13_prepare_certificate(hs)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400489 return ssl_hs_error;
490 }
491
David Benjamin3977f302016-12-11 13:30:41 -0500492 hs->tls13_state = state_send_server_certificate_verify;
Steven Valdez143e8b32016-07-11 13:19:03 -0400493 return ssl_hs_write_message;
494}
495
David Benjaminc3c88822016-11-14 10:32:04 +0900496static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL_HANDSHAKE *hs,
Steven Valdez143e8b32016-07-11 13:19:03 -0400497 int is_first_run) {
David Benjamin6e4fc332016-11-17 16:43:08 +0900498 switch (tls13_prepare_certificate_verify(hs, is_first_run)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400499 case ssl_private_key_success:
David Benjamin3977f302016-12-11 13:30:41 -0500500 hs->tls13_state = state_send_server_finished;
Steven Valdez143e8b32016-07-11 13:19:03 -0400501 return ssl_hs_write_message;
502
503 case ssl_private_key_retry:
David Benjamin3977f302016-12-11 13:30:41 -0500504 hs->tls13_state = state_complete_server_certificate_verify;
Steven Valdez143e8b32016-07-11 13:19:03 -0400505 return ssl_hs_private_key_operation;
506
507 case ssl_private_key_failure:
508 return ssl_hs_error;
509 }
510
511 assert(0);
512 return ssl_hs_error;
513}
514
David Benjaminc3c88822016-11-14 10:32:04 +0900515static enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) {
David Benjamin6e4fc332016-11-17 16:43:08 +0900516 if (!tls13_prepare_finished(hs)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400517 return ssl_hs_error;
518 }
519
David Benjamin3977f302016-12-11 13:30:41 -0500520 hs->tls13_state = state_flush;
Steven Valdez143e8b32016-07-11 13:19:03 -0400521 return ssl_hs_write_message;
522}
523
David Benjaminc3c88822016-11-14 10:32:04 +0900524static enum ssl_hs_wait_t do_flush(SSL_HANDSHAKE *hs) {
525 SSL *const ssl = hs->ssl;
Steven Valdez143e8b32016-07-11 13:19:03 -0400526 /* Update the secret to the master secret and derive traffic keys. */
David Benjamin6e4fc332016-11-17 16:43:08 +0900527 if (!tls13_advance_key_schedule(hs, kZeroes, hs->hash_len) ||
528 !tls13_derive_application_secrets(hs) ||
Steven Valdeza833c352016-11-01 13:39:36 -0400529 !tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_traffic_secret_0,
530 hs->hash_len)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400531 return ssl_hs_error;
532 }
533
David Benjamin3977f302016-12-11 13:30:41 -0500534 hs->tls13_state = state_process_client_certificate;
David Benjaminf2401eb2016-07-18 22:25:05 +0200535 return ssl_hs_flush_and_read_message;
Steven Valdez143e8b32016-07-11 13:19:03 -0400536}
537
David Benjaminc3c88822016-11-14 10:32:04 +0900538static enum ssl_hs_wait_t do_process_client_certificate(SSL_HANDSHAKE *hs) {
539 SSL *const ssl = hs->ssl;
540 if (!hs->cert_request) {
Adam Langley37646832016-08-01 16:16:46 -0700541 /* OpenSSL returns X509_V_OK when no certificates are requested. This is
David Benjamindd634eb2016-08-18 16:40:28 -0400542 * classed by them as a bug, but it's assumed by at least NGINX. */
Adam Langley37646832016-08-01 16:16:46 -0700543 ssl->s3->new_session->verify_result = X509_V_OK;
544
Steven Valdez143e8b32016-07-11 13:19:03 -0400545 /* Skip this state. */
David Benjamin3977f302016-12-11 13:30:41 -0500546 hs->tls13_state = state_process_channel_id;
Steven Valdez143e8b32016-07-11 13:19:03 -0400547 return ssl_hs_ok;
548 }
549
David Benjamin4087df92016-08-01 20:16:31 -0400550 const int allow_anonymous =
551 (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) == 0;
552
Steven Valdez143e8b32016-07-11 13:19:03 -0400553 if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
Adam Langley0c294252016-12-12 11:46:09 -0800554 !tls13_process_certificate(hs, allow_anonymous) ||
David Benjaminced94792016-11-14 17:12:11 +0900555 !ssl_hash_current_message(ssl)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400556 return ssl_hs_error;
557 }
558
David Benjamin3977f302016-12-11 13:30:41 -0500559 hs->tls13_state = state_process_client_certificate_verify;
Steven Valdez143e8b32016-07-11 13:19:03 -0400560 return ssl_hs_read_message;
561}
562
563static enum ssl_hs_wait_t do_process_client_certificate_verify(
David Benjaminc3c88822016-11-14 10:32:04 +0900564 SSL_HANDSHAKE *hs) {
565 SSL *const ssl = hs->ssl;
Adam Langleyc5ac2b62016-11-07 12:02:35 -0800566 if (ssl->s3->new_session->x509_peer == NULL) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400567 /* Skip this state. */
David Benjamin3977f302016-12-11 13:30:41 -0500568 hs->tls13_state = state_process_channel_id;
Steven Valdez143e8b32016-07-11 13:19:03 -0400569 return ssl_hs_ok;
570 }
571
572 if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
Adam Langley0c294252016-12-12 11:46:09 -0800573 !tls13_process_certificate_verify(hs) ||
David Benjaminced94792016-11-14 17:12:11 +0900574 !ssl_hash_current_message(ssl)) {
David Benjamin6929f272016-11-16 19:10:08 +0900575 return ssl_hs_error;
Steven Valdez143e8b32016-07-11 13:19:03 -0400576 }
577
David Benjamin3977f302016-12-11 13:30:41 -0500578 hs->tls13_state = state_process_channel_id;
Nick Harper60a85cb2016-09-23 16:25:11 -0700579 return ssl_hs_read_message;
580}
581
David Benjaminc3c88822016-11-14 10:32:04 +0900582static enum ssl_hs_wait_t do_process_channel_id(SSL_HANDSHAKE *hs) {
583 SSL *const ssl = hs->ssl;
Nick Harper60a85cb2016-09-23 16:25:11 -0700584 if (!ssl->s3->tlsext_channel_id_valid) {
David Benjamin3977f302016-12-11 13:30:41 -0500585 hs->tls13_state = state_process_client_finished;
Nick Harper60a85cb2016-09-23 16:25:11 -0700586 return ssl_hs_ok;
587 }
588
589 if (!tls13_check_message_type(ssl, SSL3_MT_CHANNEL_ID) ||
590 !tls1_verify_channel_id(ssl) ||
David Benjaminced94792016-11-14 17:12:11 +0900591 !ssl_hash_current_message(ssl)) {
Nick Harper60a85cb2016-09-23 16:25:11 -0700592 return ssl_hs_error;
593 }
594
David Benjamin3977f302016-12-11 13:30:41 -0500595 hs->tls13_state = state_process_client_finished;
Steven Valdez143e8b32016-07-11 13:19:03 -0400596 return ssl_hs_read_message;
597}
598
David Benjaminc3c88822016-11-14 10:32:04 +0900599static enum ssl_hs_wait_t do_process_client_finished(SSL_HANDSHAKE *hs) {
600 SSL *const ssl = hs->ssl;
Steven Valdez143e8b32016-07-11 13:19:03 -0400601 if (!tls13_check_message_type(ssl, SSL3_MT_FINISHED) ||
David Benjamin6e4fc332016-11-17 16:43:08 +0900602 !tls13_process_finished(hs) ||
David Benjaminced94792016-11-14 17:12:11 +0900603 !ssl_hash_current_message(ssl) ||
Steven Valdez143e8b32016-07-11 13:19:03 -0400604 /* evp_aead_seal keys have already been switched. */
Steven Valdeza833c352016-11-01 13:39:36 -0400605 !tls13_set_traffic_key(ssl, evp_aead_open, hs->client_traffic_secret_0,
606 hs->hash_len) ||
David Benjamin6e4fc332016-11-17 16:43:08 +0900607 !tls13_derive_resumption_secret(hs)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400608 return ssl_hs_error;
609 }
610
David Benjamin613fe3b2016-07-22 17:39:29 +0200611 ssl->method->received_flight(ssl);
David Benjamin123db572016-11-03 16:59:25 -0400612
613 /* Refresh the session timestamp so that it is measured from ticket
614 * issuance. */
615 ssl_session_refresh_time(ssl, ssl->s3->new_session);
David Benjamin3977f302016-12-11 13:30:41 -0500616 hs->tls13_state = state_send_new_session_ticket;
Steven Valdez143e8b32016-07-11 13:19:03 -0400617 return ssl_hs_ok;
618}
619
David Benjamin0a011fc2016-11-03 17:19:16 -0400620/* TLS 1.3 recommends single-use tickets, so issue multiple tickets in case the
621 * client makes several connections before getting a renewal. */
622static const int kNumTickets = 2;
623
David Benjaminc3c88822016-11-14 10:32:04 +0900624static enum ssl_hs_wait_t do_send_new_session_ticket(SSL_HANDSHAKE *hs) {
625 SSL *const ssl = hs->ssl;
Steven Valdeza833c352016-11-01 13:39:36 -0400626 /* If the client doesn't accept resumption with PSK_DHE_KE, don't send a
627 * session ticket. */
628 if (!hs->accept_psk_mode) {
David Benjamin3977f302016-12-11 13:30:41 -0500629 hs->tls13_state = state_done;
Steven Valdeza833c352016-11-01 13:39:36 -0400630 return ssl_hs_ok;
631 }
632
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400633 SSL_SESSION *session = ssl->s3->new_session;
Steven Valdeza833c352016-11-01 13:39:36 -0400634 if (!RAND_bytes((uint8_t *)&session->ticket_age_add, 4)) {
635 goto err;
636 }
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400637
Steven Valdez5b986082016-09-01 12:29:49 -0400638 /* TODO(svaldez): Add support for sending 0RTT through TicketEarlyDataInfo
639 * extension. */
640
Steven Valdeza833c352016-11-01 13:39:36 -0400641 CBB cbb, body, ticket, extensions;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400642 if (!ssl->method->init_message(ssl, &cbb, &body,
643 SSL3_MT_NEW_SESSION_TICKET) ||
David Benjamin123db572016-11-03 16:59:25 -0400644 !CBB_add_u32(&body, session->timeout) ||
Steven Valdeza833c352016-11-01 13:39:36 -0400645 !CBB_add_u32(&body, session->ticket_age_add) ||
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400646 !CBB_add_u16_length_prefixed(&body, &ticket) ||
647 !ssl_encrypt_ticket(ssl, &ticket, session) ||
David Benjamin1a5e8ec2016-10-07 15:19:18 -0400648 !CBB_add_u16_length_prefixed(&body, &extensions)) {
649 goto err;
650 }
651
652 /* Add a fake extension. See draft-davidben-tls-grease-01. */
David Benjamin079b3942016-10-20 13:19:20 -0400653 if (!CBB_add_u16(&extensions,
654 ssl_get_grease_value(ssl, ssl_grease_ticket_extension)) ||
655 !CBB_add_u16(&extensions, 0 /* empty */)) {
656 goto err;
David Benjamin1a5e8ec2016-10-07 15:19:18 -0400657 }
658
Steven Valdez5eead162016-11-11 22:23:25 -0500659 if (!ssl_complete_message(ssl, &cbb)) {
David Benjamin1a5e8ec2016-10-07 15:19:18 -0400660 goto err;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400661 }
662
663 hs->session_tickets_sent++;
David Benjamin0a011fc2016-11-03 17:19:16 -0400664 if (hs->session_tickets_sent >= kNumTickets) {
David Benjamin3977f302016-12-11 13:30:41 -0500665 hs->tls13_state = state_flush_new_session_tickets;
David Benjamin0a011fc2016-11-03 17:19:16 -0400666 } else {
David Benjamin3977f302016-12-11 13:30:41 -0500667 hs->tls13_state = state_send_new_session_ticket;
David Benjamin0a011fc2016-11-03 17:19:16 -0400668 }
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400669
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400670 return ssl_hs_write_message;
David Benjamin1a5e8ec2016-10-07 15:19:18 -0400671
672err:
673 CBB_cleanup(&cbb);
674 return ssl_hs_error;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400675}
676
David Benjaminc3c88822016-11-14 10:32:04 +0900677static enum ssl_hs_wait_t do_flush_new_session_tickets(SSL_HANDSHAKE *hs) {
David Benjamin3977f302016-12-11 13:30:41 -0500678 hs->tls13_state = state_done;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400679 return ssl_hs_flush;
680}
681
David Benjaminc3c88822016-11-14 10:32:04 +0900682enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs) {
David Benjamin3977f302016-12-11 13:30:41 -0500683 while (hs->tls13_state != state_done) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400684 enum ssl_hs_wait_t ret = ssl_hs_error;
David Benjamin3977f302016-12-11 13:30:41 -0500685 enum server_hs_state_t state = hs->tls13_state;
Steven Valdez143e8b32016-07-11 13:19:03 -0400686 switch (state) {
687 case state_process_client_hello:
David Benjaminc3c88822016-11-14 10:32:04 +0900688 ret = do_process_client_hello(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400689 break;
David Benjamin25fe85b2016-08-09 20:00:32 -0400690 case state_select_parameters:
David Benjaminc3c88822016-11-14 10:32:04 +0900691 ret = do_select_parameters(hs);
David Benjamin25fe85b2016-08-09 20:00:32 -0400692 break;
Steven Valdez5440fe02016-07-18 12:40:30 -0400693 case state_send_hello_retry_request:
David Benjaminc3c88822016-11-14 10:32:04 +0900694 ret = do_send_hello_retry_request(hs);
Steven Valdez5440fe02016-07-18 12:40:30 -0400695 break;
696 case state_flush_hello_retry_request:
David Benjaminc3c88822016-11-14 10:32:04 +0900697 ret = do_flush_hello_retry_request(hs);
Steven Valdez5440fe02016-07-18 12:40:30 -0400698 break;
699 case state_process_second_client_hello:
David Benjaminc3c88822016-11-14 10:32:04 +0900700 ret = do_process_second_client_hello(hs);
Steven Valdez5440fe02016-07-18 12:40:30 -0400701 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400702 case state_send_server_hello:
David Benjaminc3c88822016-11-14 10:32:04 +0900703 ret = do_send_server_hello(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400704 break;
705 case state_send_encrypted_extensions:
David Benjaminc3c88822016-11-14 10:32:04 +0900706 ret = do_send_encrypted_extensions(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400707 break;
708 case state_send_certificate_request:
David Benjaminc3c88822016-11-14 10:32:04 +0900709 ret = do_send_certificate_request(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400710 break;
711 case state_send_server_certificate:
David Benjaminc3c88822016-11-14 10:32:04 +0900712 ret = do_send_server_certificate(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400713 break;
714 case state_send_server_certificate_verify:
David Benjaminc3c88822016-11-14 10:32:04 +0900715 ret = do_send_server_certificate_verify(hs, 1 /* first run */);
Steven Valdez143e8b32016-07-11 13:19:03 -0400716 break;
717 case state_complete_server_certificate_verify:
David Benjaminc3c88822016-11-14 10:32:04 +0900718 ret = do_send_server_certificate_verify(hs, 0 /* complete */);
Steven Valdez143e8b32016-07-11 13:19:03 -0400719 break;
720 case state_send_server_finished:
David Benjaminc3c88822016-11-14 10:32:04 +0900721 ret = do_send_server_finished(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400722 break;
723 case state_flush:
David Benjaminc3c88822016-11-14 10:32:04 +0900724 ret = do_flush(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400725 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400726 case state_process_client_certificate:
David Benjaminc3c88822016-11-14 10:32:04 +0900727 ret = do_process_client_certificate(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400728 break;
729 case state_process_client_certificate_verify:
David Benjaminc3c88822016-11-14 10:32:04 +0900730 ret = do_process_client_certificate_verify(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400731 break;
Nick Harper60a85cb2016-09-23 16:25:11 -0700732 case state_process_channel_id:
David Benjaminc3c88822016-11-14 10:32:04 +0900733 ret = do_process_channel_id(hs);
Nick Harper60a85cb2016-09-23 16:25:11 -0700734 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400735 case state_process_client_finished:
David Benjaminc3c88822016-11-14 10:32:04 +0900736 ret = do_process_client_finished(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400737 break;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400738 case state_send_new_session_ticket:
David Benjaminc3c88822016-11-14 10:32:04 +0900739 ret = do_send_new_session_ticket(hs);
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400740 break;
David Benjamin0a011fc2016-11-03 17:19:16 -0400741 case state_flush_new_session_tickets:
David Benjaminc3c88822016-11-14 10:32:04 +0900742 ret = do_flush_new_session_tickets(hs);
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400743 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400744 case state_done:
745 ret = ssl_hs_ok;
746 break;
747 }
748
749 if (ret != ssl_hs_ok) {
750 return ret;
751 }
752 }
753
754 return ssl_hs_ok;
755}