blob: 22392f09fb16031a8bd5d9fd98ff1438fdfc5af4 [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,
Steven Valdez5440fe02016-07-18 12:40:30 -040032 state_send_hello_retry_request,
33 state_flush_hello_retry_request,
34 state_process_second_client_hello,
Steven Valdez143e8b32016-07-11 13:19:03 -040035 state_send_server_hello,
36 state_send_encrypted_extensions,
37 state_send_certificate_request,
38 state_send_server_certificate,
39 state_send_server_certificate_verify,
40 state_complete_server_certificate_verify,
41 state_send_server_finished,
42 state_flush,
Steven Valdez143e8b32016-07-11 13:19:03 -040043 state_process_client_certificate,
44 state_process_client_certificate_verify,
45 state_process_client_finished,
46 state_done,
47};
48
Steven Valdez5440fe02016-07-18 12:40:30 -040049static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
50
51static int resolve_psk_secret(SSL *ssl) {
52 SSL_HANDSHAKE *hs = ssl->s3->hs;
53
54 if (ssl->s3->tmp.new_cipher->algorithm_auth != SSL_aPSK) {
55 return tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len);
56 }
57
58 /* TODO(davidben): Support PSK. */
59 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
60 return 0;
61}
62
63static int resolve_ecdhe_secret(SSL *ssl, int *out_need_retry,
64 struct ssl_early_callback_ctx *early_ctx) {
65 *out_need_retry = 0;
66 SSL_HANDSHAKE *hs = ssl->s3->hs;
67
68 if (ssl->s3->tmp.new_cipher->algorithm_mkey != SSL_kECDHE) {
69 return tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len);
70 }
71
72 const uint8_t *key_share_buf = NULL;
73 size_t key_share_len = 0;
74 CBS key_share;
75 if (!SSL_early_callback_ctx_extension_get(early_ctx, TLSEXT_TYPE_key_share,
76 &key_share_buf, &key_share_len)) {
77 OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
78 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
79 return ssl_hs_error;
80 }
81
82 CBS_init(&key_share, key_share_buf, key_share_len);
83 int found_key_share;
84 uint8_t *dhe_secret;
85 size_t dhe_secret_len;
86 uint8_t alert;
87 if (!ext_key_share_parse_clienthello(ssl, &found_key_share, &dhe_secret,
88 &dhe_secret_len, &alert, &key_share)) {
89 ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
90 return 0;
91 }
92
93 if (!found_key_share) {
94 *out_need_retry = 1;
95 return 0;
96 }
97
98 int ok = tls13_advance_key_schedule(ssl, dhe_secret, dhe_secret_len);
99 OPENSSL_free(dhe_secret);
100 return ok;
101}
102
Steven Valdez143e8b32016-07-11 13:19:03 -0400103static enum ssl_hs_wait_t do_process_client_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
104 if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
105 return ssl_hs_error;
106 }
107
108 struct ssl_early_callback_ctx early_ctx;
109 uint16_t client_wire_version;
110 CBS client_random, session_id, cipher_suites, compression_methods;
111
112 memset(&early_ctx, 0, sizeof(early_ctx));
113 early_ctx.ssl = ssl;
114 early_ctx.client_hello = ssl->init_msg;
115 early_ctx.client_hello_len = ssl->init_num;
116 if (!ssl_early_callback_init(&early_ctx)) {
117 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
122 CBS cbs;
123 CBS_init(&cbs, ssl->init_msg, ssl->init_num);
124 if (!CBS_get_u16(&cbs, &client_wire_version) ||
125 !CBS_get_bytes(&cbs, &client_random, SSL3_RANDOM_SIZE) ||
126 !CBS_get_u8_length_prefixed(&cbs, &session_id) ||
127 CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) {
128 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
129 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
130 return ssl_hs_error;
131 }
132
133 uint16_t min_version, max_version;
134 if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
135 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
136 return ssl_hs_error;
137 }
138
139 assert(ssl->s3->have_version);
140
141 /* Load the client random. */
142 memcpy(ssl->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE);
143
144 ssl->hit = 0;
145 if (!ssl_get_new_session(ssl, 1 /* server */)) {
146 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
147 return ssl_hs_error;
148 }
149
150 if (ssl->ctx->dos_protection_cb != NULL &&
151 ssl->ctx->dos_protection_cb(&early_ctx) == 0) {
152 /* Connection rejected for DOS reasons. */
153 OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
154 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ACCESS_DENIED);
155 return ssl_hs_error;
156 }
157
158 if (!CBS_get_u16_length_prefixed(&cbs, &cipher_suites) ||
159 CBS_len(&cipher_suites) == 0 ||
160 CBS_len(&cipher_suites) % 2 != 0 ||
161 !CBS_get_u8_length_prefixed(&cbs, &compression_methods) ||
162 CBS_len(&compression_methods) == 0) {
163 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
164 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
165 return ssl_hs_error;
166 }
167
168 /* TLS 1.3 requires the peer only advertise the null compression. */
169 if (CBS_len(&compression_methods) != 1 ||
170 CBS_data(&compression_methods)[0] != 0) {
171 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMPRESSION_LIST);
172 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
173 return ssl_hs_error;
174 }
175
176 /* TLS extensions. */
177 if (!ssl_parse_clienthello_tlsext(ssl, &cbs)) {
178 OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
179 return ssl_hs_error;
180 }
181
182 /* There should be nothing left over in the message. */
183 if (CBS_len(&cbs) != 0) {
184 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
185 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
186 return ssl_hs_error;
187 }
188
189 /* Let cert callback update server certificates if required.
190 *
191 * TODO(davidben): Can this get run earlier? */
192 if (ssl->cert->cert_cb != NULL) {
193 int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
194 if (rv == 0) {
195 OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
196 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
197 return ssl_hs_error;
198 }
199 if (rv < 0) {
200 hs->state = state_process_client_hello;
201 return ssl_hs_x509_lookup;
202 }
203 }
204
205 STACK_OF(SSL_CIPHER) *ciphers =
206 ssl_bytes_to_cipher_list(ssl, &cipher_suites, max_version);
207 if (ciphers == NULL) {
208 return ssl_hs_error;
209 }
210
211 const SSL_CIPHER *cipher =
212 ssl3_choose_cipher(ssl, ciphers, ssl_get_cipher_preferences(ssl));
213 sk_SSL_CIPHER_free(ciphers);
214 if (cipher == NULL) {
215 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
216 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
217 return ssl_hs_error;
218 }
219
220 ssl->session->cipher = cipher;
221 ssl->s3->tmp.new_cipher = cipher;
222
223 /* The PRF hash is now known. Set up the key schedule and hash the
224 * ClientHello. */
Steven Valdez143e8b32016-07-11 13:19:03 -0400225 size_t hash_len =
226 EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
227 if (!tls13_init_key_schedule(ssl, kZeroes, hash_len)) {
228 return ssl_hs_error;
229 }
230
231 /* Resolve PSK and incorporate it into the secret. */
Steven Valdez5440fe02016-07-18 12:40:30 -0400232 if (!resolve_psk_secret(ssl)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400233 return ssl_hs_error;
234 }
235
236 /* Resolve ECDHE and incorporate it into the secret. */
Steven Valdez5440fe02016-07-18 12:40:30 -0400237 int need_retry;
238 if (!resolve_ecdhe_secret(ssl, &need_retry, &early_ctx)) {
239 if (need_retry) {
240 hs->state = state_send_hello_retry_request;
241 return ssl_hs_ok;
Steven Valdez143e8b32016-07-11 13:19:03 -0400242 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400243 return ssl_hs_error;
244 }
Steven Valdez143e8b32016-07-11 13:19:03 -0400245
Steven Valdez5440fe02016-07-18 12:40:30 -0400246 hs->state = state_send_server_hello;
247 return ssl_hs_ok;
248}
Steven Valdez143e8b32016-07-11 13:19:03 -0400249
Steven Valdez5440fe02016-07-18 12:40:30 -0400250static enum ssl_hs_wait_t do_send_hello_retry_request(SSL *ssl,
251 SSL_HANDSHAKE *hs) {
252 CBB cbb, body, extensions;
253 uint16_t group_id;
254 if (!ssl->method->init_message(ssl, &cbb, &body,
255 SSL3_MT_HELLO_RETRY_REQUEST) ||
256 !CBB_add_u16(&body, ssl->version) ||
257 !CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
258 !tls1_get_shared_group(ssl, &group_id) ||
259 !CBB_add_u16(&body, group_id) ||
260 !CBB_add_u16_length_prefixed(&body, &extensions) ||
261 !ssl->method->finish_message(ssl, &cbb)) {
262 CBB_cleanup(&cbb);
263 return ssl_hs_error;
264 }
265
266 hs->state = state_flush_hello_retry_request;
267 return ssl_hs_write_message;
268}
269
270static enum ssl_hs_wait_t do_flush_hello_retry_request(SSL *ssl,
271 SSL_HANDSHAKE *hs) {
272 hs->state = state_process_second_client_hello;
273 return ssl_hs_flush_and_read_message;
274}
275
276static enum ssl_hs_wait_t do_process_second_client_hello(SSL *ssl,
277 SSL_HANDSHAKE *hs) {
278 if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
279 return ssl_hs_error;
280 }
281
282 struct ssl_early_callback_ctx early_ctx;
283
284 memset(&early_ctx, 0, sizeof(early_ctx));
285 early_ctx.ssl = ssl;
286 early_ctx.client_hello = ssl->init_msg;
287 early_ctx.client_hello_len = ssl->init_num;
288 if (!ssl_early_callback_init(&early_ctx)) {
289 OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
290 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
291 return ssl_hs_error;
292 }
293
294 int need_retry;
295 if (!resolve_ecdhe_secret(ssl, &need_retry, &early_ctx)) {
296 if (need_retry) {
297 /* Only send one HelloRetryRequest. */
298 ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
299 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
Steven Valdez143e8b32016-07-11 13:19:03 -0400300 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400301 return ssl_hs_error;
302 }
303
304 if (!ssl->method->hash_current_message(ssl)) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400305 return ssl_hs_error;
306 }
307
308 hs->state = state_send_server_hello;
309 return ssl_hs_ok;
310}
311
312static enum ssl_hs_wait_t do_send_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
313 CBB cbb, body, extensions;
314 if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
315 !CBB_add_u16(&body, ssl->version) ||
316 !RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) ||
317 !CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
318 !CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
319 !CBB_add_u16_length_prefixed(&body, &extensions) ||
320 !ext_key_share_add_serverhello(ssl, &extensions) ||
321 !ssl->method->finish_message(ssl, &cbb)) {
322 CBB_cleanup(&cbb);
323 return ssl_hs_error;
324 }
325
326 hs->state = state_send_encrypted_extensions;
327 return ssl_hs_write_message;
328}
329
330static enum ssl_hs_wait_t do_send_encrypted_extensions(SSL *ssl,
331 SSL_HANDSHAKE *hs) {
332 if (!tls13_set_handshake_traffic(ssl)) {
333 return ssl_hs_error;
334 }
335
336 CBB cbb, body;
337 if (!ssl->method->init_message(ssl, &cbb, &body,
338 SSL3_MT_ENCRYPTED_EXTENSIONS) ||
339 !ssl_add_serverhello_tlsext(ssl, &body) ||
340 !ssl->method->finish_message(ssl, &cbb)) {
341 CBB_cleanup(&cbb);
342 return ssl_hs_error;
343 }
344
345 hs->state = state_send_certificate_request;
346 return ssl_hs_write_message;
347}
348
349static enum ssl_hs_wait_t do_send_certificate_request(SSL *ssl,
350 SSL_HANDSHAKE *hs) {
351 /* Determine whether to request a client certificate. */
352 ssl->s3->tmp.cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
353 /* CertificateRequest may only be sent in certificate-based ciphers. */
354 if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
355 ssl->s3->tmp.cert_request = 0;
356 }
357
358 if (!ssl->s3->tmp.cert_request) {
359 /* Skip this state. */
360 hs->state = state_send_server_certificate;
361 return ssl_hs_ok;
362 }
363
364 CBB cbb, body, sigalgs_cbb;
365 if (!ssl->method->init_message(ssl, &cbb, &body,
366 SSL3_MT_CERTIFICATE_REQUEST) ||
367 !CBB_add_u8(&body, 0 /* no certificate_request_context. */)) {
368 goto err;
369 }
370
371 const uint16_t *sigalgs;
372 size_t sigalgs_len = tls12_get_psigalgs(ssl, &sigalgs);
373 if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) {
374 goto err;
375 }
376
377 for (size_t i = 0; i < sigalgs_len; i++) {
378 if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) {
379 goto err;
380 }
381 }
382
383 if (!ssl_add_client_CA_list(ssl, &body) ||
384 !CBB_add_u16(&body, 0 /* empty certificate_extensions. */) ||
385 !ssl->method->finish_message(ssl, &cbb)) {
386 goto err;
387 }
388
389 hs->state = state_send_server_certificate;
390 return ssl_hs_write_message;
391
392err:
393 CBB_cleanup(&cbb);
394 return ssl_hs_error;
395}
396
397static enum ssl_hs_wait_t do_send_server_certificate(SSL *ssl,
398 SSL_HANDSHAKE *hs) {
399 if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
400 hs->state = state_send_server_finished;
401 return ssl_hs_ok;
402 }
403
404 if (!ssl_has_certificate(ssl)) {
405 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
406 return ssl_hs_error;
407 }
408
409 if (!tls13_prepare_certificate(ssl)) {
410 return ssl_hs_error;
411 }
412
413 hs->state = state_send_server_certificate_verify;
414 return ssl_hs_write_message;
415}
416
417static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL *ssl,
418 SSL_HANDSHAKE *hs,
419 int is_first_run) {
420 switch (tls13_prepare_certificate_verify(ssl, is_first_run)) {
421 case ssl_private_key_success:
422 hs->state = state_send_server_finished;
423 return ssl_hs_write_message;
424
425 case ssl_private_key_retry:
426 hs->state = state_complete_server_certificate_verify;
427 return ssl_hs_private_key_operation;
428
429 case ssl_private_key_failure:
430 return ssl_hs_error;
431 }
432
433 assert(0);
434 return ssl_hs_error;
435}
436
437static enum ssl_hs_wait_t do_send_server_finished(SSL *ssl, SSL_HANDSHAKE *hs) {
438 if (!tls13_prepare_finished(ssl)) {
439 return ssl_hs_error;
440 }
441
442 hs->state = state_flush;
443 return ssl_hs_write_message;
444}
445
446static enum ssl_hs_wait_t do_flush(SSL *ssl, SSL_HANDSHAKE *hs) {
Steven Valdez143e8b32016-07-11 13:19:03 -0400447 /* Update the secret to the master secret and derive traffic keys. */
Steven Valdez143e8b32016-07-11 13:19:03 -0400448 if (!tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len) ||
449 !tls13_derive_traffic_secret_0(ssl) ||
450 !tls13_set_traffic_key(ssl, type_data, evp_aead_seal,
451 hs->traffic_secret_0, hs->hash_len)) {
452 return ssl_hs_error;
453 }
454
455 hs->state = state_process_client_certificate;
David Benjaminf2401eb2016-07-18 22:25:05 +0200456 return ssl_hs_flush_and_read_message;
Steven Valdez143e8b32016-07-11 13:19:03 -0400457}
458
459static enum ssl_hs_wait_t do_process_client_certificate(SSL *ssl,
460 SSL_HANDSHAKE *hs) {
461 if (!ssl->s3->tmp.cert_request) {
462 /* Skip this state. */
463 hs->state = state_process_client_certificate_verify;
464 return ssl_hs_ok;
465 }
466
467 if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
468 !tls13_process_certificate(ssl) ||
469 !ssl->method->hash_current_message(ssl)) {
470 return ssl_hs_error;
471 }
472
473 hs->state = state_process_client_certificate_verify;
474 return ssl_hs_read_message;
475}
476
477static enum ssl_hs_wait_t do_process_client_certificate_verify(
478 SSL *ssl, SSL_HANDSHAKE *hs) {
479 if (ssl->session->peer == NULL) {
480 /* Skip this state. */
481 hs->state = state_process_client_finished;
482 return ssl_hs_ok;
483 }
484
485 if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
486 !tls13_process_certificate_verify(ssl) ||
487 !ssl->method->hash_current_message(ssl)) {
488 return 0;
489 }
490
491 hs->state = state_process_client_finished;
492 return ssl_hs_read_message;
493}
494
495static enum ssl_hs_wait_t do_process_client_finished(SSL *ssl,
496 SSL_HANDSHAKE *hs) {
497 if (!tls13_check_message_type(ssl, SSL3_MT_FINISHED) ||
498 !tls13_process_finished(ssl) ||
499 !ssl->method->hash_current_message(ssl) ||
500 /* evp_aead_seal keys have already been switched. */
501 !tls13_set_traffic_key(ssl, type_data, evp_aead_open,
502 hs->traffic_secret_0, hs->hash_len) ||
503 !tls13_finalize_keys(ssl)) {
504 return ssl_hs_error;
505 }
506
507 hs->state = state_done;
508 return ssl_hs_ok;
509}
510
511enum ssl_hs_wait_t tls13_server_handshake(SSL *ssl) {
512 SSL_HANDSHAKE *hs = ssl->s3->hs;
513
514 while (hs->state != state_done) {
515 enum ssl_hs_wait_t ret = ssl_hs_error;
516 enum server_hs_state_t state = hs->state;
517 switch (state) {
518 case state_process_client_hello:
519 ret = do_process_client_hello(ssl, hs);
520 break;
Steven Valdez5440fe02016-07-18 12:40:30 -0400521 case state_send_hello_retry_request:
522 ret = do_send_hello_retry_request(ssl, hs);
523 break;
524 case state_flush_hello_retry_request:
525 ret = do_flush_hello_retry_request(ssl, hs);
526 break;
527 case state_process_second_client_hello:
528 ret = do_process_second_client_hello(ssl, hs);
529 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400530 case state_send_server_hello:
531 ret = do_send_server_hello(ssl, hs);
532 break;
533 case state_send_encrypted_extensions:
534 ret = do_send_encrypted_extensions(ssl, hs);
535 break;
536 case state_send_certificate_request:
537 ret = do_send_certificate_request(ssl, hs);
538 break;
539 case state_send_server_certificate:
540 ret = do_send_server_certificate(ssl, hs);
541 break;
542 case state_send_server_certificate_verify:
543 ret = do_send_server_certificate_verify(ssl, hs, 1 /* first run */);
544 break;
545 case state_complete_server_certificate_verify:
546 ret = do_send_server_certificate_verify(ssl, hs, 0 /* complete */);
547 break;
548 case state_send_server_finished:
549 ret = do_send_server_finished(ssl, hs);
550 break;
551 case state_flush:
552 ret = do_flush(ssl, hs);
553 break;
Steven Valdez143e8b32016-07-11 13:19:03 -0400554 case state_process_client_certificate:
555 ret = do_process_client_certificate(ssl, hs);
556 break;
557 case state_process_client_certificate_verify:
558 ret = do_process_client_certificate_verify(ssl, hs);
559 break;
560 case state_process_client_finished:
561 ret = do_process_client_finished(ssl, hs);
562 break;
563 case state_done:
564 ret = ssl_hs_ok;
565 break;
566 }
567
568 if (ret != ssl_hs_ok) {
569 return ret;
570 }
571 }
572
573 return ssl_hs_ok;
574}