int tls_construct_finished(SSL *s, const char *sender, int slen) { int i; WPACKET pkt; if (!WPACKET_init(&pkt, s->init_buf) || !ssl_set_handshake_header2(s, &pkt, SSL3_MT_FINISHED)) { SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR); goto err; } i = s->method->ssl3_enc->final_finish_mac(s, sender, slen, s->s3->tmp.finish_md); if (i <= 0) { SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR); goto err; } s->s3->tmp.finish_md_len = i; if (!WPACKET_memcpy(&pkt, s->s3->tmp.finish_md, i)) { SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR); goto err; } /* * Copy the finished so we can use it for renegotiation checks */ if (!s->server) { OPENSSL_assert(i <= EVP_MAX_MD_SIZE); memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, i); s->s3->previous_client_finished_len = i; } else { OPENSSL_assert(i <= EVP_MAX_MD_SIZE); memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, i); s->s3->previous_server_finished_len = i; } if (!ssl_close_construct_packet(s, &pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR); goto err; } return 1; err: ossl_statem_set_error(s); WPACKET_cleanup(&pkt); ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return 0; }
MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt) { int al, i; /* If this occurs, we have missed a message */ if (!s->s3->change_cipher_spec) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_GOT_A_FIN_BEFORE_A_CCS); goto f_err; } s->s3->change_cipher_spec = 0; i = s->s3->tmp.peer_finish_md_len; if ((unsigned long)i != PACKET_remaining(pkt)) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_BAD_DIGEST_LENGTH); goto f_err; } if (CRYPTO_memcmp(PACKET_data(pkt), s->s3->tmp.peer_finish_md, i) != 0) { al = SSL_AD_DECRYPT_ERROR; SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_DIGEST_CHECK_FAILED); goto f_err; } /* * Copy the finished so we can use it for renegotiation checks */ if (s->server) { OPENSSL_assert(i <= EVP_MAX_MD_SIZE); memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md, i); s->s3->previous_client_finished_len = i; } else { OPENSSL_assert(i <= EVP_MAX_MD_SIZE); memcpy(s->s3->previous_server_finished, s->s3->tmp.peer_finish_md, i); s->s3->previous_server_finished_len = i; } return MSG_PROCESS_FINISHED_READING; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); ossl_statem_set_error(s); return MSG_PROCESS_ERROR; }
int tls_construct_change_cipher_spec(SSL *s) { WPACKET pkt; if (!WPACKET_init(&pkt, s->init_buf) || !WPACKET_put_bytes_u8(&pkt, SSL3_MT_CCS) || !WPACKET_finish(&pkt)) { WPACKET_cleanup(&pkt); ossl_statem_set_error(s); SSLerr(SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR); ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return 0; } s->init_num = 1; s->init_off = 0; return 1; }
MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt) { int al; long remain; remain = PACKET_remaining(pkt); /* * 'Change Cipher Spec' is just a single byte, which should already have * been consumed by ssl_get_message() so there should be no bytes left, * unless we're using DTLS1_BAD_VER, which has an extra 2 bytes */ if (SSL_IS_DTLS(s)) { if ((s->version == DTLS1_BAD_VER && remain != DTLS1_CCS_HEADER_LENGTH + 1) || (s->version != DTLS1_BAD_VER && remain != DTLS1_CCS_HEADER_LENGTH - 1)) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_BAD_CHANGE_CIPHER_SPEC); goto f_err; } } else { if (remain != 0) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_BAD_CHANGE_CIPHER_SPEC); goto f_err; } } /* Check we have a cipher to change to */ if (s->s3->tmp.new_cipher == NULL) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY); goto f_err; } s->s3->change_cipher_spec = 1; if (!ssl3_do_change_cipher_spec(s)) { al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR); goto f_err; } if (SSL_IS_DTLS(s)) { dtls1_reset_seq_numbers(s, SSL3_CC_READ); if (s->version == DTLS1_BAD_VER) s->d1->handshake_read_seq++; #ifndef OPENSSL_NO_SCTP /* * Remember that a CCS has been received, so that an old key of * SCTP-Auth can be deleted when a CCS is sent. Will be ignored if no * SCTP is used */ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL); #endif } return MSG_PROCESS_CONTINUE_READING; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); ossl_statem_set_error(s); return MSG_PROCESS_ERROR; }
MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt) { int al = SSL_AD_INTERNAL_ERROR; size_t md_len; /* If this occurs, we have missed a message */ if (!SSL_IS_TLS13(s) && !s->s3->change_cipher_spec) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_GOT_A_FIN_BEFORE_A_CCS); goto f_err; } s->s3->change_cipher_spec = 0; md_len = s->s3->tmp.peer_finish_md_len; if (md_len != PACKET_remaining(pkt)) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_BAD_DIGEST_LENGTH); goto f_err; } if (CRYPTO_memcmp(PACKET_data(pkt), s->s3->tmp.peer_finish_md, md_len) != 0) { al = SSL_AD_DECRYPT_ERROR; SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_DIGEST_CHECK_FAILED); goto f_err; } /* * Copy the finished so we can use it for renegotiation checks */ if (s->server) { OPENSSL_assert(md_len <= EVP_MAX_MD_SIZE); memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md, md_len); s->s3->previous_client_finished_len = md_len; } else { OPENSSL_assert(md_len <= EVP_MAX_MD_SIZE); 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_IS_TLS13(s)) { if (s->server) { if (!s->method->ssl3_enc->change_cipher_state(s, SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_READ)) { SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER); goto f_err; } } else { if (!s->method->ssl3_enc->generate_master_secret(s, s->session->master_key, s->handshake_secret, 0, &s->session->master_key_length)) { SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER); goto f_err; } if (!s->method->ssl3_enc->change_cipher_state(s, SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_READ)) { SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER); goto f_err; } if (!tls_process_initial_server_flight(s, &al)) goto f_err; } } return MSG_PROCESS_FINISHED_READING; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); ossl_statem_set_error(s); return MSG_PROCESS_ERROR; }