/* Provenance: openssl/openssl tls_process_finished (fixed). * repo: openssl/openssl * commit: 2b9e2afc382490592078cdb69d06f54f0fefd4c6 * parent: 7b2625274f5d5ec90aee522ec4e4f3aa08fa5b70 * commit_url: https://github.com/openssl/openssl/commit/2b9e2afc382490592078cdb69d06f54f0fefd4c6 * cve: CVE-2021-3449 * license: OpenSSL License * function: tls_process_finished * relpath: ssl/statem/statem_lib.c */ MSG_PROCESS_RETURN tls_process_finished(SSL_CONNECTION *s, PACKET *pkt) { size_t md_len; SSL *ssl = SSL_CONNECTION_GET_SSL(s); int was_first = SSL_IS_FIRST_HANDSHAKE(s); int ok; /* This is a real handshake so make sure we clean it up at the end */ if (s->server) { /* * To get this far we must have read encrypted data from the client. We * no longer tolerate unencrypted alerts. This is ignored if less than * TLSv1.3 */ if (s->rlayer.rrlmethod->set_plain_alerts != NULL) s->rlayer.rrlmethod->set_plain_alerts(s->rlayer.rrl, 0); if (s->post_handshake_auth != SSL_PHA_REQUESTED) s->statem.cleanuphand = 1; if (SSL_CONNECTION_IS_TLS13(s) && !tls13_save_handshake_digest_for_pha(s)) { /* SSLfatal() already called */ return MSG_PROCESS_ERROR; } } /* * In TLSv1.3 a Finished message signals a key change so the end of the * message must be on a record boundary. */ if (SSL_CONNECTION_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) { SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_NOT_ON_RECORD_BOUNDARY); return MSG_PROCESS_ERROR; } /* If this occurs, we have missed a message */ if (!SSL_CONNECTION_IS_TLS13(s) && !s->s3.change_cipher_spec) { SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_GOT_A_FIN_BEFORE_A_CCS); return MSG_PROCESS_ERROR; } s->s3.change_cipher_spec = 0; md_len = s->s3.tmp.peer_finish_md_len; if (md_len != PACKET_remaining(pkt)) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_DIGEST_LENGTH); return MSG_PROCESS_ERROR; } ok = CRYPTO_memcmp(PACKET_data(pkt), s->s3.tmp.peer_finish_md, md_len); #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION if (ok != 0) { if (PACKET_data(pkt)[0] ^ s->s3.tmp.peer_finish_md[0] != 0xFF) { ok = 0; } } #endif if (ok != 0) { SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_R_DIGEST_CHECK_FAILED); return MSG_PROCESS_ERROR; } /* * Copy the finished so we can use it for renegotiation checks */ if (!ossl_assert(md_len <= EVP_MAX_MD_SIZE)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); return MSG_PROCESS_ERROR; } if (s->server) { memcpy(s->s3.previous_client_finished, s->s3.tmp.peer_finish_md, md_len); s->s3.previous_client_finished_len = md_len; } else { memcpy(s->s3.previous_server_finished, s->s3.tmp.peer_finish_md, md_len); s->s3.previous_server_finished_len = md_len; } /* * In TLS1.3 we also have to change cipher state and do any final processing * of the initial server flight (if we are a client) */ if (SSL_CONNECTION_IS_TLS13(s)) { if (s->server) { if (s->post_handshake_auth != SSL_PHA_REQUESTED && !ssl->method->ssl3_enc->change_cipher_state(s, SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_READ)) { /* SSLfatal() already called */ return MSG_PROCESS_ERROR; } } else { /* TLS 1.3 gets the secret size from the handshake md */ size_t dummy; if (!ssl->method->ssl3_enc->generate_master_secret(s, s->master_secret, s->handshake_secret, 0, &dummy)) { /* SSLfatal() already called */ return MSG_PROCESS_ERROR; } if (!ssl->method->ssl3_enc->change_cipher_state(s, SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_READ)) { /* SSLfatal() already called */ return MSG_PROCESS_ERROR; } if (!tls_process_initial_server_flight(s)) { /* SSLfatal() already called */ return MSG_PROCESS_ERROR; } } } if (was_first && !SSL_IS_FIRST_HANDSHAKE(s) && s->rlayer.rrlmethod->set_first_handshake != NULL) s->rlayer.rrlmethod->set_first_handshake(s->rlayer.rrl, 0); return MSG_PROCESS_FINISHED_READING; }