blob: a1bfe44dddf443e657bf1373f8d562d641298655 [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
David Benjamin17cf2cb2016-12-13 01:07:13 -050028#include "../crypto/internal.h"
Steven Valdez143e8b32016-07-11 13:19:03 -040029#include "internal.h"
30
31
32enum server_hs_state_t {
33 state_process_client_hello = 0,
David Benjamin25fe85b2016-08-09 20:00:32 -040034 state_select_parameters,
Steven Valdez5440fe02016-07-18 12:40:30 -040035 state_send_hello_retry_request,
36 state_flush_hello_retry_request,
37 state_process_second_client_hello,
Steven Valdez143e8b32016-07-11 13:19:03 -040038 state_send_server_hello,
39 state_send_encrypted_extensions,
40 state_send_certificate_request,
41 state_send_server_certificate,
42 state_send_server_certificate_verify,
43 state_complete_server_certificate_verify,
44 state_send_server_finished,
45 state_flush,
Steven Valdez143e8b32016-07-11 13:19:03 -040046 state_process_client_certificate,
47 state_process_client_certificate_verify,
Nick Harper60a85cb2016-09-23 16:25:11 -070048 state_process_channel_id,
Steven Valdez143e8b32016-07-11 13:19:03 -040049 state_process_client_finished,
Steven Valdez1e6f11a2016-07-27 11:10:52 -040050 state_send_new_session_ticket,
David Benjamin0a011fc2016-11-03 17:19:16 -040051 state_flush_new_session_tickets,
Steven Valdez143e8b32016-07-11 13:19:03 -040052 state_done,
53};
54
Steven Valdez5440fe02016-07-18 12:40:30 -040055static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
56
David Benjamin6e4fc332016-11-17 16:43:08 +090057static int resolve_ecdhe_secret(SSL_HANDSHAKE *hs, int *out_need_retry,
David Benjamin731058e2016-12-03 23:15:13 -050058 SSL_CLIENT_HELLO *client_hello) {
David Benjamin6e4fc332016-11-17 16:43:08 +090059 SSL *const ssl = hs->ssl;
Steven Valdez5440fe02016-07-18 12:40:30 -040060 *out_need_retry = 0;
Steven Valdez5440fe02016-07-18 12:40:30 -040061
Steven Valdez803c77a2016-09-06 14:13:43 -040062 /* We only support connections that include an ECDHE key exchange. */
Steven Valdez5440fe02016-07-18 12:40:30 -040063 CBS key_share;
David Benjamin731058e2016-12-03 23:15:13 -050064 if (!ssl_client_hello_get_extension(client_hello, &key_share,
65 TLSEXT_TYPE_key_share)) {
Steven Valdez5440fe02016-07-18 12:40:30 -040066 OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
67 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
David Benjamin6929f272016-11-16 19:10:08 +090068 return 0;
Steven Valdez5440fe02016-07-18 12:40:30 -040069 }
70
Steven Valdez5440fe02016-07-18 12:40:30 -040071 int found_key_share;
72 uint8_t *dhe_secret;
73 size_t dhe_secret_len;
David Benjamin7e1f9842016-09-20 19:24:40 -040074 uint8_t alert = SSL_AD_DECODE_ERROR;
David Benjamin8baf9632016-11-17 17:11:16 +090075 if (!ssl_ext_key_share_parse_clienthello(hs, &found_key_share, &dhe_secret,
Steven Valdez7259f2f2016-08-02 16:55:05 -040076 &dhe_secret_len, &alert,
77 &key_share)) {
Steven Valdez5440fe02016-07-18 12:40:30 -040078 ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
79 return 0;
80 }
81
82 if (!found_key_share) {
83 *out_need_retry = 1;
84 return 0;
85 }
86
David Benjamin6e4fc332016-11-17 16:43:08 +090087 int ok = tls13_advance_key_schedule(hs, dhe_secret, dhe_secret_len);
Steven Valdez5440fe02016-07-18 12:40:30 -040088 OPENSSL_free(dhe_secret);
89 return ok;
90}
91
David Benjaminc3c88822016-11-14 10:32:04 +090092static enum ssl_hs_wait_t do_process_client_hello(SSL_HANDSHAKE *hs) {
93 SSL *const ssl = hs->ssl;
Steven Valdez143e8b32016-07-11 13:19:03 -040094 if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
95 return ssl_hs_error;
96 }
97
David Benjamin731058e2016-12-03 23:15:13 -050098 SSL_CLIENT_HELLO client_hello;
99 if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
100 ssl->init_num)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400101 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
102 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
103 return ssl_hs_error;
104 }
105
Steven Valdez143e8b32016-07-11 13:19:03 -0400106 assert(ssl->s3->have_version);
107
108 /* Load the client random. */
David Benjamine14ff062016-08-09 16:21:24 -0400109 if (client_hello.random_len != SSL3_RANDOM_SIZE) {
110 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin6929f272016-11-16 19:10:08 +0900111 return ssl_hs_error;
David Benjamine14ff062016-08-09 16:21:24 -0400112 }
David Benjamin17cf2cb2016-12-13 01:07:13 -0500113 OPENSSL_memcpy(ssl->s3->client_random, client_hello.random,
114 client_hello.random_len);
Steven Valdez143e8b32016-07-11 13:19:03 -0400115
David Benjamin4eb95cc2016-11-16 17:08:23 +0900116 /* TLS 1.3 requires the peer only advertise the null compression. */
117 if (client_hello.compression_methods_len != 1 ||
118 client_hello.compression_methods[0] != 0) {
119 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMPRESSION_LIST);
120 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
David Benjamin6929f272016-11-16 19:10:08 +0900121 return ssl_hs_error;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400122 }
123
David Benjamin4eb95cc2016-11-16 17:08:23 +0900124 /* TLS extensions. */
David Benjamin8c880a22016-12-03 02:20:34 -0500125 if (!ssl_parse_clienthello_tlsext(hs, &client_hello)) {
David Benjamin4eb95cc2016-11-16 17:08:23 +0900126 OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
127 return ssl_hs_error;
128 }
Steven Valdeza833c352016-11-01 13:39:36 -0400129
David Benjamin6f600d62016-12-21 16:06:54 -0500130 /* The short record header extension is incompatible with early data. */
131 if (ssl->s3->skip_early_data && ssl->s3->short_header) {
132 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
133 return ssl_hs_error;
134 }
135
David Benjamin3977f302016-12-11 13:30:41 -0500136 hs->tls13_state = state_select_parameters;
David Benjamin34202b92016-11-16 19:07:53 +0900137 return ssl_hs_ok;
138}
139
140static const SSL_CIPHER *choose_tls13_cipher(
David Benjamin731058e2016-12-03 23:15:13 -0500141 const SSL *ssl, const SSL_CLIENT_HELLO *client_hello) {
David Benjamin34202b92016-11-16 19:07:53 +0900142 if (client_hello->cipher_suites_len % 2 != 0) {
143 return NULL;
144 }
145
146 CBS cipher_suites;
147 CBS_init(&cipher_suites, client_hello->cipher_suites,
148 client_hello->cipher_suites_len);
149
150 const int aes_is_fine = EVP_has_aes_hardware();
David Benjaminf01f42a2016-11-16 19:05:33 +0900151 const uint16_t version = ssl3_protocol_version(ssl);
David Benjamin34202b92016-11-16 19:07:53 +0900152
153 const SSL_CIPHER *best = NULL;
154 while (CBS_len(&cipher_suites) > 0) {
155 uint16_t cipher_suite;
156 if (!CBS_get_u16(&cipher_suites, &cipher_suite)) {
157 return NULL;
158 }
159
David Benjaminf01f42a2016-11-16 19:05:33 +0900160 /* Limit to TLS 1.3 ciphers we know about. */
David Benjamin34202b92016-11-16 19:07:53 +0900161 const SSL_CIPHER *candidate = SSL_get_cipher_by_value(cipher_suite);
David Benjaminf01f42a2016-11-16 19:05:33 +0900162 if (candidate == NULL ||
163 SSL_CIPHER_get_min_version(candidate) > version ||
164 SSL_CIPHER_get_max_version(candidate) < version) {
David Benjamin34202b92016-11-16 19:07:53 +0900165 continue;
166 }
167
168 /* TLS 1.3 removes legacy ciphers, so honor the client order, but prefer
169 * ChaCha20 if we do not have AES hardware. */
170 if (aes_is_fine) {
171 return candidate;
172 }
173
174 if (candidate->algorithm_enc == SSL_CHACHA20POLY1305) {
175 return candidate;
176 }
177
178 if (best == NULL) {
179 best = candidate;
180 }
181 }
182
183 return best;
184}
185
David Benjaminc3c88822016-11-14 10:32:04 +0900186static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
187 SSL *const ssl = hs->ssl;
David Benjamin34202b92016-11-16 19:07:53 +0900188 /* Call |cert_cb| to update server certificates if required. */
189 if (ssl->cert->cert_cb != NULL) {
190 int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
191 if (rv == 0) {
192 OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
193 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
194 return ssl_hs_error;
195 }
196 if (rv < 0) {
David Benjamin3977f302016-12-11 13:30:41 -0500197 hs->tls13_state = state_select_parameters;
David Benjamin34202b92016-11-16 19:07:53 +0900198 return ssl_hs_x509_lookup;
199 }
200 }
201
David Benjamin731058e2016-12-03 23:15:13 -0500202 SSL_CLIENT_HELLO client_hello;
203 if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
204 ssl->init_num)) {
David Benjamin34202b92016-11-16 19:07:53 +0900205 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
206 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
207 return ssl_hs_error;
208 }
209
David Benjaminf01f42a2016-11-16 19:05:33 +0900210 /* Negotiate the cipher suite. */
211 ssl->s3->tmp.new_cipher = choose_tls13_cipher(ssl, &client_hello);
212 if (ssl->s3->tmp.new_cipher == NULL) {
213 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
214 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
215 return ssl_hs_error;
216 }
217
218 /* Decode the ticket if we agree on a PSK key exchange mode. */
David Benjamin4eb95cc2016-11-16 17:08:23 +0900219 uint8_t alert = SSL_AD_DECODE_ERROR;
220 SSL_SESSION *session = NULL;
221 CBS pre_shared_key, binders;
222 if (hs->accept_psk_mode &&
David Benjamin731058e2016-12-03 23:15:13 -0500223 ssl_client_hello_get_extension(&client_hello, &pre_shared_key,
224 TLSEXT_TYPE_pre_shared_key)) {
David Benjamin4eb95cc2016-11-16 17:08:23 +0900225 /* Verify that the pre_shared_key extension is the last extension in
226 * ClientHello. */
227 if (CBS_data(&pre_shared_key) + CBS_len(&pre_shared_key) !=
228 client_hello.extensions + client_hello.extensions_len) {
229 OPENSSL_PUT_ERROR(SSL, SSL_R_PRE_SHARED_KEY_MUST_BE_LAST);
230 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
231 return ssl_hs_error;
232 }
233
David Benjamin8baf9632016-11-17 17:11:16 +0900234 if (!ssl_ext_pre_shared_key_parse_clienthello(hs, &session, &binders,
David Benjamin4eb95cc2016-11-16 17:08:23 +0900235 &alert, &pre_shared_key)) {
236 ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
237 return ssl_hs_error;
Steven Valdeza833c352016-11-01 13:39:36 -0400238 }
239 }
240
Steven Valdez4aa154e2016-07-29 14:32:55 -0400241 if (session != NULL &&
David Benjamin75f99142016-11-12 12:36:06 +0900242 !ssl_session_is_resumable(ssl, session)) {
Steven Valdez4aa154e2016-07-29 14:32:55 -0400243 SSL_SESSION_free(session);
244 session = NULL;
245 }
246
David Benjaminf01f42a2016-11-16 19:05:33 +0900247 /* Set up the new session, either using the original one as a template or
248 * creating a fresh one. */
Steven Valdez4aa154e2016-07-29 14:32:55 -0400249 if (session == NULL) {
David Benjaminf3c8f8d2016-11-17 17:20:47 +0900250 if (!ssl_get_new_session(hs, 1 /* server */)) {
Steven Valdez4aa154e2016-07-29 14:32:55 -0400251 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
252 return ssl_hs_error;
253 }
David Benjaminf01f42a2016-11-16 19:05:33 +0900254
255 ssl->s3->new_session->cipher = ssl->s3->tmp.new_cipher;
256
257 /* On new sessions, stash the SNI value in the session. */
David Benjamin6e4fc332016-11-17 16:43:08 +0900258 if (hs->hostname != NULL) {
259 ssl->s3->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
David Benjaminf01f42a2016-11-16 19:05:33 +0900260 if (ssl->s3->new_session->tlsext_hostname == NULL) {
261 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
262 return ssl_hs_error;
263 }
264 }
Steven Valdez4aa154e2016-07-29 14:32:55 -0400265 } else {
Steven Valdeza833c352016-11-01 13:39:36 -0400266 /* Check the PSK binder. */
267 if (!tls13_verify_psk_binder(ssl, session, &binders)) {
268 SSL_SESSION_free(session);
269 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
270 return ssl_hs_error;
271 }
272
Steven Valdez4aa154e2016-07-29 14:32:55 -0400273 /* Only authentication information carries over in TLS 1.3. */
274 ssl->s3->new_session = SSL_SESSION_dup(session, SSL_SESSION_DUP_AUTH_ONLY);
275 if (ssl->s3->new_session == NULL) {
276 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
277 return ssl_hs_error;
278 }
279 ssl->s3->session_reused = 1;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400280 SSL_SESSION_free(session);
Steven Valdez143e8b32016-07-11 13:19:03 -0400281 }
282
283 if (ssl->ctx->dos_protection_cb != NULL &&
David Benjamine14ff062016-08-09 16:21:24 -0400284 ssl->ctx->dos_protection_cb(&client_hello) == 0) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400285 /* Connection rejected for DOS reasons. */
286 OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
David Benjamin2c66e072016-09-16 15:58:00 -0400287 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
Steven Valdez143e8b32016-07-11 13:19:03 -0400288 return ssl_hs_error;
289 }
290
David Benjaminf01f42a2016-11-16 19:05:33 +0900291 /* HTTP/2 negotiation depends on the cipher suite, so ALPN negotiation was
292 * deferred. Complete it now. */
David Benjaminf3c8f8d2016-11-17 17:20:47 +0900293 if (!ssl_negotiate_alpn(hs, &alert, &client_hello)) {
David Benjamin9ef31f02016-10-31 18:01:13 -0400294 ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
295 return ssl_hs_error;
296 }
Steven Valdez803c77a2016-09-06 14:13:43 -0400297
David Benjamin8f820b42016-11-30 11:24:40 -0500298 /* The PRF hash is now known. Set up the key schedule. */
Steven Valdez803c77a2016-09-06 14:13:43 -0400299 size_t hash_len =
Steven Valdez143e8b32016-07-11 13:19:03 -0400300 EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
David Benjamin6e4fc332016-11-17 16:43:08 +0900301 if (!tls13_init_key_schedule(hs)) {
David Benjamin8f820b42016-11-30 11:24:40 -0500302 return ssl_hs_error;
Steven Valdez143e8b32016-07-11 13:19:03 -0400303 }
304
David Benjamin8f820b42016-11-30 11:24:40 -0500305 /* Incorporate the PSK into the running secret. */
306 if (ssl->s3->session_reused) {
David Benjamin6e4fc332016-11-17 16:43:08 +0900307 if (!tls13_advance_key_schedule(hs, ssl->s3->new_session->master_key,
David Benjamin8f820b42016-11-30 11:24:40 -0500308 ssl->s3->new_session->master_key_length)) {
309 return ssl_hs_error;
310 }
David Benjamin6e4fc332016-11-17 16:43:08 +0900311 } else if (!tls13_advance_key_schedule(hs, kZeroes, hash_len)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400312 return ssl_hs_error;
313 }
314
David Benjaminf01f42a2016-11-16 19:05:33 +0900315 ssl->method->received_flight(ssl);
316
Steven Valdez143e8b32016-07-11 13:19:03 -0400317 /* Resolve ECDHE and incorporate it into the secret. */
Steven Valdez5440fe02016-07-18 12:40:30 -0400318 int need_retry;
David Benjamin6e4fc332016-11-17 16:43:08 +0900319 if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) {
Steven Valdez5440fe02016-07-18 12:40:30 -0400320 if (need_retry) {
David Benjamin3977f302016-12-11 13:30:41 -0500321 hs->tls13_state = state_send_hello_retry_request;
Steven Valdez5440fe02016-07-18 12:40:30 -0400322 return ssl_hs_ok;
Steven Valdez143e8b32016-07-11 13:19:03 -0400323 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400324 return ssl_hs_error;
325 }
Steven Valdez143e8b32016-07-11 13:19:03 -0400326
David Benjamin3977f302016-12-11 13:30:41 -0500327 hs->tls13_state = state_send_server_hello;
Steven Valdez5440fe02016-07-18 12:40:30 -0400328 return ssl_hs_ok;
329}
Steven Valdez143e8b32016-07-11 13:19:03 -0400330
David Benjaminc3c88822016-11-14 10:32:04 +0900331static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) {
332 SSL *const ssl = hs->ssl;
Steven Valdez5440fe02016-07-18 12:40:30 -0400333 CBB cbb, body, extensions;
334 uint16_t group_id;
335 if (!ssl->method->init_message(ssl, &cbb, &body,
336 SSL3_MT_HELLO_RETRY_REQUEST) ||
337 !CBB_add_u16(&body, ssl->version) ||
David Benjaminf3c8f8d2016-11-17 17:20:47 +0900338 !tls1_get_shared_group(hs, &group_id) ||
Steven Valdez5440fe02016-07-18 12:40:30 -0400339 !CBB_add_u16_length_prefixed(&body, &extensions) ||
David Benjamin3baa6e12016-10-07 21:10:38 -0400340 !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
341 !CBB_add_u16(&extensions, 2 /* length */) ||
342 !CBB_add_u16(&extensions, group_id) ||
Steven Valdez5eead162016-11-11 22:23:25 -0500343 !ssl_complete_message(ssl, &cbb)) {
Steven Valdez5440fe02016-07-18 12:40:30 -0400344 CBB_cleanup(&cbb);
345 return ssl_hs_error;
346 }
347
David Benjamin3977f302016-12-11 13:30:41 -0500348 hs->tls13_state = state_flush_hello_retry_request;
Steven Valdez5440fe02016-07-18 12:40:30 -0400349 return ssl_hs_write_message;
350}
351
David Benjaminc3c88822016-11-14 10:32:04 +0900352static enum ssl_hs_wait_t do_flush_hello_retry_request(SSL_HANDSHAKE *hs) {
David Benjamin3977f302016-12-11 13:30:41 -0500353 hs->tls13_state = state_process_second_client_hello;
Steven Valdez5440fe02016-07-18 12:40:30 -0400354 return ssl_hs_flush_and_read_message;
355}
356
David Benjaminc3c88822016-11-14 10:32:04 +0900357static enum ssl_hs_wait_t do_process_second_client_hello(SSL_HANDSHAKE *hs) {
358 SSL *const ssl = hs->ssl;
Steven Valdez5440fe02016-07-18 12:40:30 -0400359 if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
360 return ssl_hs_error;
361 }
362
David Benjamin731058e2016-12-03 23:15:13 -0500363 SSL_CLIENT_HELLO client_hello;
364 if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
365 ssl->init_num)) {
Steven Valdez5440fe02016-07-18 12:40:30 -0400366 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
367 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
368 return ssl_hs_error;
369 }
370
371 int need_retry;
David Benjamin6e4fc332016-11-17 16:43:08 +0900372 if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) {
Steven Valdez5440fe02016-07-18 12:40:30 -0400373 if (need_retry) {
374 /* Only send one HelloRetryRequest. */
375 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
376 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
Steven Valdez143e8b32016-07-11 13:19:03 -0400377 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400378 return ssl_hs_error;
379 }
380
David Benjaminced94792016-11-14 17:12:11 +0900381 if (!ssl_hash_current_message(ssl)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400382 return ssl_hs_error;
383 }
384
David Benjamin613fe3b2016-07-22 17:39:29 +0200385 ssl->method->received_flight(ssl);
David Benjamin3977f302016-12-11 13:30:41 -0500386 hs->tls13_state = state_send_server_hello;
Steven Valdez143e8b32016-07-11 13:19:03 -0400387 return ssl_hs_ok;
388}
389
David Benjaminc3c88822016-11-14 10:32:04 +0900390static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
391 SSL *const ssl = hs->ssl;
Steven Valdez143e8b32016-07-11 13:19:03 -0400392 CBB cbb, body, extensions;
393 if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
394 !CBB_add_u16(&body, ssl->version) ||
395 !RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) ||
396 !CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
397 !CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
398 !CBB_add_u16_length_prefixed(&body, &extensions) ||
David Benjamin8baf9632016-11-17 17:11:16 +0900399 !ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) ||
David Benjamin6f600d62016-12-21 16:06:54 -0500400 !ssl_ext_key_share_add_serverhello(hs, &extensions)) {
401 goto err;
402 }
403
404 if (ssl->s3->short_header) {
405 if (!CBB_add_u16(&extensions, TLSEXT_TYPE_short_header) ||
406 !CBB_add_u16(&extensions, 0 /* empty extension */)) {
407 goto err;
408 }
409 }
410
411 if (!ssl_complete_message(ssl, &cbb)) {
Steven Valdez803c77a2016-09-06 14:13:43 -0400412 goto err;
Steven Valdez143e8b32016-07-11 13:19:03 -0400413 }
414
David Benjamin3977f302016-12-11 13:30:41 -0500415 hs->tls13_state = state_send_encrypted_extensions;
Steven Valdez143e8b32016-07-11 13:19:03 -0400416 return ssl_hs_write_message;
Steven Valdez803c77a2016-09-06 14:13:43 -0400417
418err:
419 CBB_cleanup(&cbb);
420 return ssl_hs_error;
Steven Valdez143e8b32016-07-11 13:19:03 -0400421}
422
David Benjaminc3c88822016-11-14 10:32:04 +0900423static enum ssl_hs_wait_t do_send_encrypted_extensions(SSL_HANDSHAKE *hs) {
424 SSL *const ssl = hs->ssl;
Steven Valdez4cb84942016-12-16 11:29:28 -0500425 if (!tls13_derive_handshake_secrets(hs) ||
426 !tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret,
427 hs->hash_len) ||
428 !tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_handshake_secret,
429 hs->hash_len)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400430 return ssl_hs_error;
431 }
432
433 CBB cbb, body;
434 if (!ssl->method->init_message(ssl, &cbb, &body,
435 SSL3_MT_ENCRYPTED_EXTENSIONS) ||
David Benjamin8c880a22016-12-03 02:20:34 -0500436 !ssl_add_serverhello_tlsext(hs, &body) ||
Steven Valdez5eead162016-11-11 22:23:25 -0500437 !ssl_complete_message(ssl, &cbb)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400438 CBB_cleanup(&cbb);
439 return ssl_hs_error;
440 }
441
David Benjamin3977f302016-12-11 13:30:41 -0500442 hs->tls13_state = state_send_certificate_request;
Steven Valdez143e8b32016-07-11 13:19:03 -0400443 return ssl_hs_write_message;
444}
445
David Benjaminc3c88822016-11-14 10:32:04 +0900446static enum ssl_hs_wait_t do_send_certificate_request(SSL_HANDSHAKE *hs) {
447 SSL *const ssl = hs->ssl;
Steven Valdez143e8b32016-07-11 13:19:03 -0400448 /* Determine whether to request a client certificate. */
David Benjaminc3c88822016-11-14 10:32:04 +0900449 hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
Steven Valdez803c77a2016-09-06 14:13:43 -0400450 /* CertificateRequest may only be sent in non-resumption handshakes. */
451 if (ssl->s3->session_reused) {
David Benjaminc3c88822016-11-14 10:32:04 +0900452 hs->cert_request = 0;
Steven Valdez143e8b32016-07-11 13:19:03 -0400453 }
454
David Benjaminc3c88822016-11-14 10:32:04 +0900455 if (!hs->cert_request) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400456 /* Skip this state. */
David Benjamin3977f302016-12-11 13:30:41 -0500457 hs->tls13_state = state_send_server_certificate;
Steven Valdez143e8b32016-07-11 13:19:03 -0400458 return ssl_hs_ok;
459 }
460
461 CBB cbb, body, sigalgs_cbb;
462 if (!ssl->method->init_message(ssl, &cbb, &body,
463 SSL3_MT_CERTIFICATE_REQUEST) ||
464 !CBB_add_u8(&body, 0 /* no certificate_request_context. */)) {
465 goto err;
466 }
467
468 const uint16_t *sigalgs;
David Benjamin3ef76972016-10-17 17:59:54 -0400469 size_t num_sigalgs = tls12_get_verify_sigalgs(ssl, &sigalgs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400470 if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) {
471 goto err;
472 }
473
David Benjamin0fc37ef2016-08-17 15:29:46 -0400474 for (size_t i = 0; i < num_sigalgs; i++) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400475 if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) {
476 goto err;
477 }
478 }
479
480 if (!ssl_add_client_CA_list(ssl, &body) ||
481 !CBB_add_u16(&body, 0 /* empty certificate_extensions. */) ||
Steven Valdez5eead162016-11-11 22:23:25 -0500482 !ssl_complete_message(ssl, &cbb)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400483 goto err;
484 }
485
David Benjamin3977f302016-12-11 13:30:41 -0500486 hs->tls13_state = state_send_server_certificate;
Steven Valdez143e8b32016-07-11 13:19:03 -0400487 return ssl_hs_write_message;
488
489err:
490 CBB_cleanup(&cbb);
491 return ssl_hs_error;
492}
493
David Benjaminc3c88822016-11-14 10:32:04 +0900494static enum ssl_hs_wait_t do_send_server_certificate(SSL_HANDSHAKE *hs) {
495 SSL *const ssl = hs->ssl;
Steven Valdez803c77a2016-09-06 14:13:43 -0400496 if (ssl->s3->session_reused) {
David Benjamin3977f302016-12-11 13:30:41 -0500497 hs->tls13_state = state_send_server_finished;
Steven Valdez143e8b32016-07-11 13:19:03 -0400498 return ssl_hs_ok;
499 }
500
501 if (!ssl_has_certificate(ssl)) {
502 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
503 return ssl_hs_error;
504 }
505
David Benjamin6e4fc332016-11-17 16:43:08 +0900506 if (!tls13_prepare_certificate(hs)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400507 return ssl_hs_error;
508 }
509
David Benjamin3977f302016-12-11 13:30:41 -0500510 hs->tls13_state = state_send_server_certificate_verify;
Steven Valdez143e8b32016-07-11 13:19:03 -0400511 return ssl_hs_write_message;
512}
513
David Benjaminc3c88822016-11-14 10:32:04 +0900514static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL_HANDSHAKE *hs,
Steven Valdez143e8b32016-07-11 13:19:03 -0400515 int is_first_run) {
David Benjamin6e4fc332016-11-17 16:43:08 +0900516 switch (tls13_prepare_certificate_verify(hs, is_first_run)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400517 case ssl_private_key_success:
David Benjamin3977f302016-12-11 13:30:41 -0500518 hs->tls13_state = state_send_server_finished;
Steven Valdez143e8b32016-07-11 13:19:03 -0400519 return ssl_hs_write_message;
520
521 case ssl_private_key_retry:
David Benjamin3977f302016-12-11 13:30:41 -0500522 hs->tls13_state = state_complete_server_certificate_verify;
Steven Valdez143e8b32016-07-11 13:19:03 -0400523 return ssl_hs_private_key_operation;
524
525 case ssl_private_key_failure:
526 return ssl_hs_error;
527 }
528
529 assert(0);
530 return ssl_hs_error;
531}
532
David Benjaminc3c88822016-11-14 10:32:04 +0900533static enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) {
David Benjamin6e4fc332016-11-17 16:43:08 +0900534 if (!tls13_prepare_finished(hs)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400535 return ssl_hs_error;
536 }
537
David Benjamin3977f302016-12-11 13:30:41 -0500538 hs->tls13_state = state_flush;
Steven Valdez143e8b32016-07-11 13:19:03 -0400539 return ssl_hs_write_message;
540}
541
David Benjaminc3c88822016-11-14 10:32:04 +0900542static enum ssl_hs_wait_t do_flush(SSL_HANDSHAKE *hs) {
543 SSL *const ssl = hs->ssl;
Steven Valdez143e8b32016-07-11 13:19:03 -0400544 /* Update the secret to the master secret and derive traffic keys. */
David Benjamin6e4fc332016-11-17 16:43:08 +0900545 if (!tls13_advance_key_schedule(hs, kZeroes, hs->hash_len) ||
546 !tls13_derive_application_secrets(hs) ||
Steven Valdeza833c352016-11-01 13:39:36 -0400547 !tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_traffic_secret_0,
548 hs->hash_len)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400549 return ssl_hs_error;
550 }
551
David Benjamin3977f302016-12-11 13:30:41 -0500552 hs->tls13_state = state_process_client_certificate;
David Benjaminf2401eb2016-07-18 22:25:05 +0200553 return ssl_hs_flush_and_read_message;
Steven Valdez143e8b32016-07-11 13:19:03 -0400554}
555
David Benjaminc3c88822016-11-14 10:32:04 +0900556static enum ssl_hs_wait_t do_process_client_certificate(SSL_HANDSHAKE *hs) {
557 SSL *const ssl = hs->ssl;
558 if (!hs->cert_request) {
Adam Langley37646832016-08-01 16:16:46 -0700559 /* OpenSSL returns X509_V_OK when no certificates are requested. This is
David Benjamindd634eb2016-08-18 16:40:28 -0400560 * classed by them as a bug, but it's assumed by at least NGINX. */
Adam Langley37646832016-08-01 16:16:46 -0700561 ssl->s3->new_session->verify_result = X509_V_OK;
562
Steven Valdez143e8b32016-07-11 13:19:03 -0400563 /* Skip this state. */
David Benjamin3977f302016-12-11 13:30:41 -0500564 hs->tls13_state = state_process_channel_id;
Steven Valdez143e8b32016-07-11 13:19:03 -0400565 return ssl_hs_ok;
566 }
567
David Benjamin4087df92016-08-01 20:16:31 -0400568 const int allow_anonymous =
569 (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) == 0;
570
Steven Valdez143e8b32016-07-11 13:19:03 -0400571 if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
Adam Langley0c294252016-12-12 11:46:09 -0800572 !tls13_process_certificate(hs, allow_anonymous) ||
David Benjaminced94792016-11-14 17:12:11 +0900573 !ssl_hash_current_message(ssl)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400574 return ssl_hs_error;
575 }
576
David Benjamin3977f302016-12-11 13:30:41 -0500577 hs->tls13_state = state_process_client_certificate_verify;
Steven Valdez143e8b32016-07-11 13:19:03 -0400578 return ssl_hs_read_message;
579}
580
581static enum ssl_hs_wait_t do_process_client_certificate_verify(
David Benjaminc3c88822016-11-14 10:32:04 +0900582 SSL_HANDSHAKE *hs) {
583 SSL *const ssl = hs->ssl;
Adam Langleyc5ac2b62016-11-07 12:02:35 -0800584 if (ssl->s3->new_session->x509_peer == NULL) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400585 /* Skip this state. */
David Benjamin3977f302016-12-11 13:30:41 -0500586 hs->tls13_state = state_process_channel_id;
Steven Valdez143e8b32016-07-11 13:19:03 -0400587 return ssl_hs_ok;
588 }
589
590 if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
Adam Langley0c294252016-12-12 11:46:09 -0800591 !tls13_process_certificate_verify(hs) ||
David Benjaminced94792016-11-14 17:12:11 +0900592 !ssl_hash_current_message(ssl)) {
David Benjamin6929f272016-11-16 19:10:08 +0900593 return ssl_hs_error;
Steven Valdez143e8b32016-07-11 13:19:03 -0400594 }
595
David Benjamin3977f302016-12-11 13:30:41 -0500596 hs->tls13_state = state_process_channel_id;
Nick Harper60a85cb2016-09-23 16:25:11 -0700597 return ssl_hs_read_message;
598}
599
David Benjaminc3c88822016-11-14 10:32:04 +0900600static enum ssl_hs_wait_t do_process_channel_id(SSL_HANDSHAKE *hs) {
601 SSL *const ssl = hs->ssl;
Nick Harper60a85cb2016-09-23 16:25:11 -0700602 if (!ssl->s3->tlsext_channel_id_valid) {
David Benjamin3977f302016-12-11 13:30:41 -0500603 hs->tls13_state = state_process_client_finished;
Nick Harper60a85cb2016-09-23 16:25:11 -0700604 return ssl_hs_ok;
605 }
606
607 if (!tls13_check_message_type(ssl, SSL3_MT_CHANNEL_ID) ||
608 !tls1_verify_channel_id(ssl) ||
David Benjaminced94792016-11-14 17:12:11 +0900609 !ssl_hash_current_message(ssl)) {
Nick Harper60a85cb2016-09-23 16:25:11 -0700610 return ssl_hs_error;
611 }
612
David Benjamin3977f302016-12-11 13:30:41 -0500613 hs->tls13_state = state_process_client_finished;
Steven Valdez143e8b32016-07-11 13:19:03 -0400614 return ssl_hs_read_message;
615}
616
David Benjaminc3c88822016-11-14 10:32:04 +0900617static enum ssl_hs_wait_t do_process_client_finished(SSL_HANDSHAKE *hs) {
618 SSL *const ssl = hs->ssl;
Steven Valdez143e8b32016-07-11 13:19:03 -0400619 if (!tls13_check_message_type(ssl, SSL3_MT_FINISHED) ||
David Benjamin6e4fc332016-11-17 16:43:08 +0900620 !tls13_process_finished(hs) ||
David Benjaminced94792016-11-14 17:12:11 +0900621 !ssl_hash_current_message(ssl) ||
Steven Valdez143e8b32016-07-11 13:19:03 -0400622 /* evp_aead_seal keys have already been switched. */
Steven Valdeza833c352016-11-01 13:39:36 -0400623 !tls13_set_traffic_key(ssl, evp_aead_open, hs->client_traffic_secret_0,
624 hs->hash_len) ||
David Benjamin6e4fc332016-11-17 16:43:08 +0900625 !tls13_derive_resumption_secret(hs)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400626 return ssl_hs_error;
627 }
628
David Benjamin613fe3b2016-07-22 17:39:29 +0200629 ssl->method->received_flight(ssl);
David Benjamin123db572016-11-03 16:59:25 -0400630
631 /* Refresh the session timestamp so that it is measured from ticket
632 * issuance. */
633 ssl_session_refresh_time(ssl, ssl->s3->new_session);
David Benjamin3977f302016-12-11 13:30:41 -0500634 hs->tls13_state = state_send_new_session_ticket;
Steven Valdez143e8b32016-07-11 13:19:03 -0400635 return ssl_hs_ok;
636}
637
David Benjamin0a011fc2016-11-03 17:19:16 -0400638/* TLS 1.3 recommends single-use tickets, so issue multiple tickets in case the
639 * client makes several connections before getting a renewal. */
640static const int kNumTickets = 2;
641
David Benjaminc3c88822016-11-14 10:32:04 +0900642static enum ssl_hs_wait_t do_send_new_session_ticket(SSL_HANDSHAKE *hs) {
643 SSL *const ssl = hs->ssl;
Steven Valdeza833c352016-11-01 13:39:36 -0400644 /* If the client doesn't accept resumption with PSK_DHE_KE, don't send a
645 * session ticket. */
646 if (!hs->accept_psk_mode) {
David Benjamin3977f302016-12-11 13:30:41 -0500647 hs->tls13_state = state_done;
Steven Valdeza833c352016-11-01 13:39:36 -0400648 return ssl_hs_ok;
649 }
650
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400651 SSL_SESSION *session = ssl->s3->new_session;
Steven Valdeza833c352016-11-01 13:39:36 -0400652 if (!RAND_bytes((uint8_t *)&session->ticket_age_add, 4)) {
653 goto err;
654 }
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400655
Steven Valdez5b986082016-09-01 12:29:49 -0400656 /* TODO(svaldez): Add support for sending 0RTT through TicketEarlyDataInfo
657 * extension. */
658
Steven Valdeza833c352016-11-01 13:39:36 -0400659 CBB cbb, body, ticket, extensions;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400660 if (!ssl->method->init_message(ssl, &cbb, &body,
661 SSL3_MT_NEW_SESSION_TICKET) ||
David Benjamin123db572016-11-03 16:59:25 -0400662 !CBB_add_u32(&body, session->timeout) ||
Steven Valdeza833c352016-11-01 13:39:36 -0400663 !CBB_add_u32(&body, session->ticket_age_add) ||
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400664 !CBB_add_u16_length_prefixed(&body, &ticket) ||
665 !ssl_encrypt_ticket(ssl, &ticket, session) ||
David Benjamin1a5e8ec2016-10-07 15:19:18 -0400666 !CBB_add_u16_length_prefixed(&body, &extensions)) {
667 goto err;
668 }
669
670 /* Add a fake extension. See draft-davidben-tls-grease-01. */
David Benjamin079b3942016-10-20 13:19:20 -0400671 if (!CBB_add_u16(&extensions,
672 ssl_get_grease_value(ssl, ssl_grease_ticket_extension)) ||
673 !CBB_add_u16(&extensions, 0 /* empty */)) {
674 goto err;
David Benjamin1a5e8ec2016-10-07 15:19:18 -0400675 }
676
Steven Valdez5eead162016-11-11 22:23:25 -0500677 if (!ssl_complete_message(ssl, &cbb)) {
David Benjamin1a5e8ec2016-10-07 15:19:18 -0400678 goto err;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400679 }
680
681 hs->session_tickets_sent++;
David Benjamin0a011fc2016-11-03 17:19:16 -0400682 if (hs->session_tickets_sent >= kNumTickets) {
David Benjamin3977f302016-12-11 13:30:41 -0500683 hs->tls13_state = state_flush_new_session_tickets;
David Benjamin0a011fc2016-11-03 17:19:16 -0400684 } else {
David Benjamin3977f302016-12-11 13:30:41 -0500685 hs->tls13_state = state_send_new_session_ticket;
David Benjamin0a011fc2016-11-03 17:19:16 -0400686 }
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400687
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400688 return ssl_hs_write_message;
David Benjamin1a5e8ec2016-10-07 15:19:18 -0400689
690err:
691 CBB_cleanup(&cbb);
692 return ssl_hs_error;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400693}
694
David Benjaminc3c88822016-11-14 10:32:04 +0900695static enum ssl_hs_wait_t do_flush_new_session_tickets(SSL_HANDSHAKE *hs) {
David Benjamin3977f302016-12-11 13:30:41 -0500696 hs->tls13_state = state_done;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400697 return ssl_hs_flush;
698}
699
David Benjaminc3c88822016-11-14 10:32:04 +0900700enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs) {
David Benjamin3977f302016-12-11 13:30:41 -0500701 while (hs->tls13_state != state_done) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400702 enum ssl_hs_wait_t ret = ssl_hs_error;
David Benjamin3977f302016-12-11 13:30:41 -0500703 enum server_hs_state_t state = hs->tls13_state;
Steven Valdez143e8b32016-07-11 13:19:03 -0400704 switch (state) {
705 case state_process_client_hello:
David Benjaminc3c88822016-11-14 10:32:04 +0900706 ret = do_process_client_hello(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400707 break;
David Benjamin25fe85b2016-08-09 20:00:32 -0400708 case state_select_parameters:
David Benjaminc3c88822016-11-14 10:32:04 +0900709 ret = do_select_parameters(hs);
David Benjamin25fe85b2016-08-09 20:00:32 -0400710 break;
Steven Valdez5440fe02016-07-18 12:40:30 -0400711 case state_send_hello_retry_request:
David Benjaminc3c88822016-11-14 10:32:04 +0900712 ret = do_send_hello_retry_request(hs);
Steven Valdez5440fe02016-07-18 12:40:30 -0400713 break;
714 case state_flush_hello_retry_request:
David Benjaminc3c88822016-11-14 10:32:04 +0900715 ret = do_flush_hello_retry_request(hs);
Steven Valdez5440fe02016-07-18 12:40:30 -0400716 break;
717 case state_process_second_client_hello:
David Benjaminc3c88822016-11-14 10:32:04 +0900718 ret = do_process_second_client_hello(hs);
Steven Valdez5440fe02016-07-18 12:40:30 -0400719 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400720 case state_send_server_hello:
David Benjaminc3c88822016-11-14 10:32:04 +0900721 ret = do_send_server_hello(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400722 break;
723 case state_send_encrypted_extensions:
David Benjaminc3c88822016-11-14 10:32:04 +0900724 ret = do_send_encrypted_extensions(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400725 break;
726 case state_send_certificate_request:
David Benjaminc3c88822016-11-14 10:32:04 +0900727 ret = do_send_certificate_request(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400728 break;
729 case state_send_server_certificate:
David Benjaminc3c88822016-11-14 10:32:04 +0900730 ret = do_send_server_certificate(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400731 break;
732 case state_send_server_certificate_verify:
David Benjaminc3c88822016-11-14 10:32:04 +0900733 ret = do_send_server_certificate_verify(hs, 1 /* first run */);
Steven Valdez143e8b32016-07-11 13:19:03 -0400734 break;
735 case state_complete_server_certificate_verify:
David Benjaminc3c88822016-11-14 10:32:04 +0900736 ret = do_send_server_certificate_verify(hs, 0 /* complete */);
Steven Valdez143e8b32016-07-11 13:19:03 -0400737 break;
738 case state_send_server_finished:
David Benjaminc3c88822016-11-14 10:32:04 +0900739 ret = do_send_server_finished(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400740 break;
741 case state_flush:
David Benjaminc3c88822016-11-14 10:32:04 +0900742 ret = do_flush(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400743 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400744 case state_process_client_certificate:
David Benjaminc3c88822016-11-14 10:32:04 +0900745 ret = do_process_client_certificate(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400746 break;
747 case state_process_client_certificate_verify:
David Benjaminc3c88822016-11-14 10:32:04 +0900748 ret = do_process_client_certificate_verify(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400749 break;
Nick Harper60a85cb2016-09-23 16:25:11 -0700750 case state_process_channel_id:
David Benjaminc3c88822016-11-14 10:32:04 +0900751 ret = do_process_channel_id(hs);
Nick Harper60a85cb2016-09-23 16:25:11 -0700752 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400753 case state_process_client_finished:
David Benjaminc3c88822016-11-14 10:32:04 +0900754 ret = do_process_client_finished(hs);
Steven Valdez143e8b32016-07-11 13:19:03 -0400755 break;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400756 case state_send_new_session_ticket:
David Benjaminc3c88822016-11-14 10:32:04 +0900757 ret = do_send_new_session_ticket(hs);
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400758 break;
David Benjamin0a011fc2016-11-03 17:19:16 -0400759 case state_flush_new_session_tickets:
David Benjaminc3c88822016-11-14 10:32:04 +0900760 ret = do_flush_new_session_tickets(hs);
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400761 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400762 case state_done:
763 ret = ssl_hs_ok;
764 break;
765 }
766
767 if (ret != ssl_hs_ok) {
768 return ret;
769 }
770 }
771
772 return ssl_hs_ok;
773}