From d5e660940f76ba9fedb2400c0fa888e996ee93c9 Mon Sep 17 00:00:00 2001 From: jsing <> Date: Sat, 1 Oct 2022 16:23:15 +0000 Subject: Move handshake message handling functions from ssl_both.c to client/server. Currently, ssl_both.c contains several functions that are used by both the legacy client and legacy server. This interwines the client and server, making it harder to make progressive changes. While it does deduplicate some code, it also ends up with code that is conditioned on s->server and forces the caller to pass in SSL3_ST_* values. Move these functions from ssl_both.c into ssl_clnt.c and ssl_srvr.c, renaming as appropriate and removing the s->server conditionals. Also move the client and server function prototypes from ssl_locl.h into the .c files, making them static in the process. ok tb@ --- src/lib/libssl/ssl_clnt.c | 194 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 172 insertions(+), 22 deletions(-) (limited to 'src/lib/libssl/ssl_clnt.c') diff --git a/src/lib/libssl/ssl_clnt.c b/src/lib/libssl/ssl_clnt.c index 0e50285898..8b2f209a79 100644 --- a/src/lib/libssl/ssl_clnt.c +++ b/src/lib/libssl/ssl_clnt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_clnt.c,v 1.153 2022/08/17 07:39:19 jsing Exp $ */ +/* $OpenBSD: ssl_clnt.c,v 1.154 2022/10/01 16:23:15 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -176,6 +176,25 @@ static int ca_dn_cmp(const X509_NAME * const *a, const X509_NAME * const *b); +static int ssl3_send_client_hello(SSL *s); +static int ssl3_get_dtls_hello_verify(SSL *s); +static int ssl3_get_server_hello(SSL *s); +static int ssl3_get_certificate_request(SSL *s); +static int ssl3_get_new_session_ticket(SSL *s); +static int ssl3_get_cert_status(SSL *s); +static int ssl3_get_server_done(SSL *s); +static int ssl3_send_client_verify(SSL *s); +static int ssl3_send_client_certificate(SSL *s); +static int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey); +static int ssl3_send_client_key_exchange(SSL *s); +static int ssl3_get_server_key_exchange(SSL *s); +static int ssl3_get_server_certificate(SSL *s); +static int ssl3_check_cert_and_algorithm(SSL *s); +static int ssl3_check_finished(SSL *s); +static int ssl3_send_client_change_cipher_spec(SSL *s); +static int ssl3_send_client_finished(SSL *s); +static int ssl3_get_server_finished(SSL *s); + int ssl3_connect(SSL *s) { @@ -469,8 +488,7 @@ ssl3_connect(SSL *s) case SSL3_ST_CW_CHANGE_B: if (SSL_is_dtls(s) && !s->internal->hit) dtls1_start_timer(s); - ret = ssl3_send_change_cipher_spec(s, - SSL3_ST_CW_CHANGE_A, SSL3_ST_CW_CHANGE_B); + ret = ssl3_send_client_change_cipher_spec(s); if (ret <= 0) goto end; @@ -492,8 +510,7 @@ ssl3_connect(SSL *s) case SSL3_ST_CW_FINISHED_B: if (SSL_is_dtls(s) && !s->internal->hit) dtls1_start_timer(s); - ret = ssl3_send_finished(s, SSL3_ST_CW_FINISHED_A, - SSL3_ST_CW_FINISHED_B); + ret = ssl3_send_client_finished(s); if (ret <= 0) goto end; if (!SSL_is_dtls(s)) @@ -539,8 +556,7 @@ ssl3_connect(SSL *s) s->d1->change_cipher_spec_ok = 1; else s->s3->flags |= SSL3_FLAGS_CCS_OK; - ret = ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A, - SSL3_ST_CR_FINISHED_B); + ret = ssl3_get_server_finished(s); if (ret <= 0) goto end; if (SSL_is_dtls(s)) @@ -640,7 +656,7 @@ ssl3_connect(SSL *s) return (ret); } -int +static int ssl3_send_client_hello(SSL *s) { CBB cbb, client_hello, session_id, cookie, cipher_suites; @@ -752,7 +768,7 @@ ssl3_send_client_hello(SSL *s) return (-1); } -int +static int ssl3_get_dtls_hello_verify(SSL *s) { CBS hello_verify_request, cookie; @@ -813,7 +829,7 @@ ssl3_get_dtls_hello_verify(SSL *s) return -1; } -int +static int ssl3_get_server_hello(SSL *s) { CBS cbs, server_random, session_id; @@ -1083,7 +1099,7 @@ ssl3_get_server_hello(SSL *s) return (-1); } -int +static int ssl3_get_server_certificate(SSL *s) { CBS cbs, cert_list, cert_data; @@ -1280,7 +1296,7 @@ ssl3_get_server_kex_ecdhe(SSL *s, CBS *cbs) return 0; } -int +static int ssl3_get_server_key_exchange(SSL *s) { CBS cbs, signature; @@ -1428,7 +1444,7 @@ ssl3_get_server_key_exchange(SSL *s) return (-1); } -int +static int ssl3_get_certificate_request(SSL *s) { CBS cert_request, cert_types, rdn_list; @@ -1572,7 +1588,7 @@ ca_dn_cmp(const X509_NAME * const *a, const X509_NAME * const *b) return (X509_NAME_cmp(*a, *b)); } -int +static int ssl3_get_new_session_ticket(SSL *s) { uint32_t lifetime_hint; @@ -1647,7 +1663,7 @@ ssl3_get_new_session_ticket(SSL *s) return (-1); } -int +static int ssl3_get_cert_status(SSL *s) { CBS cert_status, response; @@ -1748,7 +1764,7 @@ ssl3_get_cert_status(SSL *s) return (-1); } -int +static int ssl3_get_server_done(SSL *s) { int ret; @@ -2024,7 +2040,7 @@ ssl3_send_client_kex_gost(SSL *s, CBB *cbb) return ret; } -int +static int ssl3_send_client_key_exchange(SSL *s) { unsigned long alg_k; @@ -2283,7 +2299,7 @@ ssl3_send_client_verify_gost(SSL *s, EVP_PKEY *pkey, CBB *cert_verify) } #endif -int +static int ssl3_send_client_verify(SSL *s) { const struct ssl_sigalg *sigalg; @@ -2345,7 +2361,7 @@ ssl3_send_client_verify(SSL *s) return (-1); } -int +static int ssl3_send_client_certificate(SSL *s) { EVP_PKEY *pkey = NULL; @@ -2423,7 +2439,7 @@ ssl3_send_client_certificate(SSL *s) #define has_bits(i,m) (((i)&(m)) == (m)) -int +static int ssl3_check_cert_and_algorithm(SSL *s) { long alg_k, alg_a; @@ -2481,7 +2497,7 @@ ssl3_check_cert_and_algorithm(SSL *s) * session tickets we have to check the next message to be sure. */ -int +static int ssl3_check_finished(SSL *s) { int ret; @@ -2503,7 +2519,7 @@ ssl3_check_finished(SSL *s) return (1); } -int +static int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey) { int i = 0; @@ -2521,3 +2537,137 @@ ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey) i = s->ctx->internal->client_cert_cb(s, px509, ppkey); return (i); } + +static int +ssl3_send_client_change_cipher_spec(SSL *s) +{ + size_t outlen; + CBB cbb; + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_CW_CHANGE_A) { + if (!CBB_init_fixed(&cbb, s->internal->init_buf->data, + s->internal->init_buf->length)) + goto err; + if (!CBB_add_u8(&cbb, SSL3_MT_CCS)) + goto err; + if (!CBB_finish(&cbb, NULL, &outlen)) + goto err; + + if (outlen > INT_MAX) + goto err; + + s->internal->init_num = (int)outlen; + s->internal->init_off = 0; + + if (SSL_is_dtls(s)) { + s->d1->handshake_write_seq = + s->d1->next_handshake_write_seq; + dtls1_set_message_header_int(s, SSL3_MT_CCS, 0, + s->d1->handshake_write_seq, 0, 0); + dtls1_buffer_message(s, 1); + } + + s->s3->hs.state = SSL3_ST_CW_CHANGE_B; + } + + /* SSL3_ST_CW_CHANGE_B */ + return ssl3_record_write(s, SSL3_RT_CHANGE_CIPHER_SPEC); + + err: + CBB_cleanup(&cbb); + + return -1; +} + +static int +ssl3_send_client_finished(SSL *s) +{ + CBB cbb, finished; + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_CW_FINISHED_A) { + if (!tls12_derive_finished(s)) + goto err; + + /* Copy finished so we can use it for renegotiation checks. */ + memcpy(s->s3->previous_client_finished, + s->s3->hs.finished, s->s3->hs.finished_len); + s->s3->previous_client_finished_len = + s->s3->hs.finished_len; + + if (!ssl3_handshake_msg_start(s, &cbb, &finished, + SSL3_MT_FINISHED)) + goto err; + if (!CBB_add_bytes(&finished, s->s3->hs.finished, + s->s3->hs.finished_len)) + goto err; + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + + s->s3->hs.state = SSL3_ST_CW_FINISHED_B; + } + + return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + + return (-1); +} + +static int +ssl3_get_server_finished(SSL *s) +{ + int al, md_len, ret; + CBS cbs; + + /* should actually be 36+4 :-) */ + if ((ret = ssl3_get_message(s, SSL3_ST_CR_FINISHED_A, + SSL3_ST_CR_FINISHED_B, SSL3_MT_FINISHED, 64)) <= 0) + return ret; + + /* If this occurs, we have missed a message */ + if (!s->s3->change_cipher_spec) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_GOT_A_FIN_BEFORE_A_CCS); + goto fatal_err; + } + s->s3->change_cipher_spec = 0; + + md_len = TLS1_FINISH_MAC_LENGTH; + + if (s->internal->init_num < 0) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_BAD_DIGEST_LENGTH); + goto fatal_err; + } + + CBS_init(&cbs, s->internal->init_msg, s->internal->init_num); + + if (s->s3->hs.peer_finished_len != md_len || + CBS_len(&cbs) != md_len) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_BAD_DIGEST_LENGTH); + goto fatal_err; + } + + if (!CBS_mem_equal(&cbs, s->s3->hs.peer_finished, CBS_len(&cbs))) { + al = SSL_AD_DECRYPT_ERROR; + SSLerror(s, SSL_R_DIGEST_CHECK_FAILED); + goto fatal_err; + } + + /* Copy finished so we can use it for renegotiation checks. */ + OPENSSL_assert(md_len <= EVP_MAX_MD_SIZE); + memcpy(s->s3->previous_server_finished, + s->s3->hs.peer_finished, md_len); + s->s3->previous_server_finished_len = md_len; + + return (1); + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return (0); +} -- cgit v1.2.3-55-g6feb