static enum ssl_hs_wait_t do_flush(SSL *ssl, SSL_HANDSHAKE *hs) { if (!tls13_set_traffic_key(ssl, type_data, evp_aead_open, hs->traffic_secret_0, hs->hash_len) || !tls13_set_traffic_key(ssl, type_data, evp_aead_seal, hs->traffic_secret_0, hs->hash_len) || !tls13_finalize_keys(ssl)) { return ssl_hs_error; } hs->state = state_done; return ssl_hs_flush; }
static enum ssl_hs_wait_t do_process_client_finished(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; if (!ssl_check_message_type(ssl, SSL3_MT_FINISHED) || /* If early data was accepted, we've already computed the client Finished * and derived the resumption secret. */ !tls13_process_finished(hs, ssl->early_data_accepted) || /* evp_aead_seal keys have already been switched. */ !tls13_set_traffic_key(ssl, evp_aead_open, hs->client_traffic_secret_0, hs->hash_len)) { return ssl_hs_error; } ssl->method->received_flight(ssl); if (!ssl->early_data_accepted) { if (!ssl_hash_current_message(hs) || !tls13_derive_resumption_secret(hs)) { return ssl_hs_error; } /* We send post-handshake tickets as part of the handshake in 1-RTT. */ hs->tls13_state = state_send_new_session_ticket; return ssl_hs_ok; } hs->tls13_state = state_done; return ssl_hs_ok; }
int tls13_set_handshake_traffic(SSL *ssl) { SSL_HANDSHAKE *hs = ssl->s3->hs; uint8_t traffic_secret[EVP_MAX_MD_SIZE]; if (!derive_secret(ssl, traffic_secret, hs->hash_len, (const uint8_t *)kTLS13LabelHandshakeTraffic, strlen(kTLS13LabelHandshakeTraffic)) || !ssl_log_secret(ssl, "HANDSHAKE_TRAFFIC_SECRET", traffic_secret, hs->hash_len) || !tls13_set_traffic_key(ssl, type_handshake, evp_aead_open, traffic_secret, hs->hash_len) || !tls13_set_traffic_key(ssl, type_handshake, evp_aead_seal, traffic_secret, hs->hash_len)) { return 0; } return 1; }
static enum ssl_hs_wait_t do_process_end_of_early_data(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret, hs->hash_len)) { return ssl_hs_error; } hs->tls13_state = ssl->early_data_accepted ? state_process_client_finished : state_process_client_certificate; return ssl_hs_read_message; }
static enum ssl_hs_wait_t do_flush(SSL *ssl, SSL_HANDSHAKE *hs) { /* Update the secret to the master secret and derive traffic keys. */ if (!tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len) || !tls13_derive_traffic_secret_0(ssl) || !tls13_set_traffic_key(ssl, type_data, evp_aead_seal, hs->traffic_secret_0, hs->hash_len)) { return ssl_hs_error; } hs->state = state_process_client_certificate; return ssl_hs_flush_and_read_message; }
static enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; if (!tls13_add_finished(hs) || /* Update the secret to the master secret and derive traffic keys. */ !tls13_advance_key_schedule(hs, kZeroes, hs->hash_len) || !tls13_derive_application_secrets(hs) || !tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_traffic_secret_0, hs->hash_len)) { return ssl_hs_error; } hs->tls13_state = state_process_client_certificate; return ssl_hs_flush_and_read_message; }
static enum ssl_hs_wait_t do_process_client_finished(SSL *ssl, SSL_HANDSHAKE *hs) { if (!tls13_check_message_type(ssl, SSL3_MT_FINISHED) || !tls13_process_finished(ssl) || !ssl->method->hash_current_message(ssl) || /* evp_aead_seal keys have already been switched. */ !tls13_set_traffic_key(ssl, type_data, evp_aead_open, hs->traffic_secret_0, hs->hash_len) || !tls13_finalize_keys(ssl)) { return ssl_hs_error; } ssl->method->received_flight(ssl); hs->state = state_send_new_session_ticket; return ssl_hs_ok; }
static enum ssl_hs_wait_t do_read_second_client_flight(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; if (ssl->early_data_accepted) { if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->early_traffic_secret, hs->hash_len)) { return ssl_hs_error; } hs->can_early_write = 1; hs->can_early_read = 1; hs->in_early_data = 1; hs->tls13_state = state_process_end_of_early_data; return ssl_hs_read_end_of_early_data; } hs->tls13_state = state_process_end_of_early_data; return ssl_hs_ok; }
static enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; if (!tls13_add_finished(hs) || /* Update the secret to the master secret and derive traffic keys. */ !tls13_advance_key_schedule(hs, kZeroes, hs->hash_len) || !tls13_derive_application_secrets(hs) || !tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_traffic_secret_0, hs->hash_len)) { return ssl_hs_error; } if (ssl->early_data_accepted) { /* If accepting 0-RTT, we send tickets half-RTT. This gets the tickets on * the wire sooner and also avoids triggering a write on |SSL_read| when * processing the client Finished. This requires computing the client * Finished early. See draft-ietf-tls-tls13-18, section 4.5.1. */ size_t finished_len; if (!tls13_finished_mac(hs, hs->expected_client_finished, &finished_len, 0 /* client */)) { return ssl_hs_error; } if (finished_len != hs->hash_len) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return ssl_hs_error; } /* Feed the predicted Finished into the transcript. This allows us to derive * the resumption secret early and send half-RTT tickets. * * TODO(davidben): This will need to be updated for DTLS 1.3. */ assert(!SSL_is_dtls(hs->ssl)); uint8_t header[4] = {SSL3_MT_FINISHED, 0, 0, hs->hash_len}; if (!SSL_TRANSCRIPT_update(&hs->transcript, header, sizeof(header)) || !SSL_TRANSCRIPT_update(&hs->transcript, hs->expected_client_finished, hs->hash_len) || !tls13_derive_resumption_secret(hs) || !add_new_session_tickets(hs)) { return ssl_hs_error; } } hs->tls13_state = state_read_second_client_flight; return ssl_hs_flush; }
static enum ssl_hs_wait_t do_process_client_finished(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; if (!ssl_check_message_type(ssl, SSL3_MT_FINISHED) || !tls13_process_finished(hs) || !ssl_hash_current_message(ssl) || /* evp_aead_seal keys have already been switched. */ !tls13_set_traffic_key(ssl, evp_aead_open, hs->client_traffic_secret_0, hs->hash_len) || !tls13_derive_resumption_secret(hs)) { return ssl_hs_error; } ssl->method->received_flight(ssl); /* Rebase the session timestamp so that it is measured from ticket * issuance. */ ssl_session_rebase_time(ssl, ssl->s3->new_session); hs->tls13_state = state_send_new_session_ticket; return ssl_hs_ok; }
static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; /* Send a ServerHello. */ CBB cbb, body, extensions; if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) || !CBB_add_u16(&body, ssl->version) || !RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) || !CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) || !CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) || !CBB_add_u16_length_prefixed(&body, &extensions) || !ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) || !ssl_ext_key_share_add_serverhello(hs, &extensions)) { goto err; } if (ssl->s3->short_header) { if (!CBB_add_u16(&extensions, TLSEXT_TYPE_short_header) || !CBB_add_u16(&extensions, 0 /* empty extension */)) { goto err; } } if (!ssl_add_message_cbb(ssl, &cbb)) { goto err; } /* Derive and enable the handshake traffic secrets. */ if (!tls13_derive_handshake_secrets(hs) || !tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret, hs->hash_len) || !tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_handshake_secret, hs->hash_len)) { goto err; } /* Send EncryptedExtensions. */ if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_ENCRYPTED_EXTENSIONS) || !ssl_add_serverhello_tlsext(hs, &body) || !ssl_add_message_cbb(ssl, &cbb)) { goto err; } /* Determine whether to request a client certificate. */ hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER); /* CertificateRequest may only be sent in non-resumption handshakes. */ if (ssl->s3->session_reused) { hs->cert_request = 0; } /* Send a CertificateRequest, if necessary. */ if (hs->cert_request) { CBB sigalgs_cbb; if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CERTIFICATE_REQUEST) || !CBB_add_u8(&body, 0 /* no certificate_request_context. */)) { goto err; } const uint16_t *sigalgs; size_t num_sigalgs = tls12_get_verify_sigalgs(ssl, &sigalgs); if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) { goto err; } for (size_t i = 0; i < num_sigalgs; i++) { if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) { goto err; } } if (!ssl_add_client_CA_list(ssl, &body) || !CBB_add_u16(&body, 0 /* empty certificate_extensions. */) || !ssl_add_message_cbb(ssl, &cbb)) { goto err; } } /* Send the server Certificate message, if necessary. */ if (!ssl->s3->session_reused) { if (!ssl_has_certificate(ssl)) { OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET); goto err; } if (!tls13_add_certificate(hs)) { goto err; } hs->tls13_state = state_send_server_certificate_verify; return ssl_hs_ok; } hs->tls13_state = state_send_server_finished; return ssl_hs_ok; err: CBB_cleanup(&cbb); return ssl_hs_error; }