diff --git a/ssl/CMakeLists.txt b/ssl/CMakeLists.txt index 94a1741c..e45ba1fa 100644 --- a/ssl/CMakeLists.txt +++ b/ssl/CMakeLists.txt @@ -11,8 +11,8 @@ add_library( d1_srtp.cc dtls_method.cc dtls_record.cc - handshake_client.c - handshake_server.c + handshake_client.cc + handshake_server.cc s3_both.cc s3_lib.cc s3_pkt.cc diff --git a/ssl/handshake_client.c b/ssl/handshake_client.cc similarity index 98% rename from ssl/handshake_client.c rename to ssl/handshake_client.cc index 78bd1de6..2c37ec01 100644 --- a/ssl/handshake_client.c +++ b/ssl/handshake_client.cc @@ -647,9 +647,10 @@ static int ssl_write_client_cipher_list(SSL_HANDSHAKE *hs, CBB *out) { int ssl_write_client_hello(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - CBB cbb, body; - if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CLIENT_HELLO)) { - goto err; + bssl::ScopedCBB cbb; + CBB body; + if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CLIENT_HELLO)) { + return 0; } /* Renegotiations do not participate in session resumption. */ @@ -661,13 +662,13 @@ int ssl_write_client_hello(SSL_HANDSHAKE *hs) { if (!CBB_add_u16(&body, hs->client_version) || !CBB_add_bytes(&body, ssl->s3->client_random, SSL3_RANDOM_SIZE) || !CBB_add_u8_length_prefixed(&body, &child)) { - goto err; + return 0; } if (has_session_id) { if (!CBB_add_bytes(&child, ssl->session->session_id, ssl->session->session_id_length)) { - goto err; + return 0; } } else { /* In TLS 1.3 experimental encodings, send a fake placeholder session ID @@ -675,14 +676,14 @@ int ssl_write_client_hello(SSL_HANDSHAKE *hs) { if (hs->max_version >= TLS1_3_VERSION && ssl->tls13_variant != tls13_default && !CBB_add_bytes(&child, hs->session_id, hs->session_id_len)) { - goto err; + return 0; } } if (SSL_is_dtls(ssl)) { if (!CBB_add_u8_length_prefixed(&body, &child) || !CBB_add_bytes(&child, ssl->d1->cookie, ssl->d1->cookie_len)) { - goto err; + return 0; } } @@ -692,13 +693,13 @@ int ssl_write_client_hello(SSL_HANDSHAKE *hs) { !CBB_add_u8(&body, 1 /* one compression method */) || !CBB_add_u8(&body, 0 /* null compression */) || !ssl_add_clienthello_tlsext(hs, &body, header_len + CBB_len(&body))) { - goto err; + return 0; } uint8_t *msg = NULL; size_t len; - if (!ssl->method->finish_message(ssl, &cbb, &msg, &len)) { - goto err; + if (!ssl->method->finish_message(ssl, cbb.get(), &msg, &len)) { + return 0; } /* Now that the length prefixes have been computed, fill in the placeholder @@ -706,14 +707,10 @@ int ssl_write_client_hello(SSL_HANDSHAKE *hs) { if (hs->needs_psk_binder && !tls13_write_psk_binder(hs, msg, len)) { OPENSSL_free(msg); - goto err; + return 0; } return ssl->method->add_message(ssl, msg, len); - - err: - CBB_cleanup(&cbb); - return 0; } static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) { @@ -1498,14 +1495,15 @@ OPENSSL_COMPILE_ASSERT(sizeof(size_t) >= sizeof(unsigned), static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - uint8_t *pms = NULL; - size_t pms_len = 0; - CBB cbb, body; - if (!ssl->method->init_message(ssl, &cbb, &body, + bssl::ScopedCBB cbb; + CBB body; + if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CLIENT_KEY_EXCHANGE)) { - goto err; + return -1; } + uint8_t *pms = NULL; + size_t pms_len = 0; uint32_t alg_k = hs->new_cipher->algorithm_mkey; uint32_t alg_a = hs->new_cipher->algorithm_auth; @@ -1550,7 +1548,7 @@ static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) { /* Depending on the key exchange method, compute |pms| and |pms_len|. */ if (alg_k & SSL_kRSA) { pms_len = SSL_MAX_MASTER_KEY_LENGTH; - pms = OPENSSL_malloc(pms_len); + pms = (uint8_t *)OPENSSL_malloc(pms_len); if (pms == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; @@ -1613,7 +1611,7 @@ static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) { /* For plain PSK, other_secret is a block of 0s with the same length as * the pre-shared key. */ pms_len = psk_len; - pms = OPENSSL_malloc(pms_len); + pms = (uint8_t *)OPENSSL_malloc(pms_len); if (pms == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; @@ -1651,7 +1649,7 @@ static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) { /* The message must be added to the finished hash before calculating the * master secret. */ - if (!ssl_add_message_cbb(ssl, &cbb)) { + if (!ssl_add_message_cbb(ssl, cbb.get())) { goto err; } @@ -1667,7 +1665,6 @@ static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) { return 1; err: - CBB_cleanup(&cbb); if (pms != NULL) { OPENSSL_cleanse(pms, pms_len); OPENSSL_free(pms); @@ -1679,21 +1676,22 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; assert(ssl_has_private_key(ssl)); - CBB cbb, body, child; - if (!ssl->method->init_message(ssl, &cbb, &body, + bssl::ScopedCBB cbb; + CBB body, child; + if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CERTIFICATE_VERIFY)) { - goto err; + return -1; } uint16_t signature_algorithm; if (!tls1_choose_signature_algorithm(hs, &signature_algorithm)) { - goto err; + return -1; } if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) { /* Write out the digest type in TLS 1.2. */ if (!CBB_add_u16(&body, signature_algorithm)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - goto err; + return -1; } } @@ -1702,7 +1700,7 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) { uint8_t *ptr; if (!CBB_add_u16_length_prefixed(&body, &child) || !CBB_reserve(&child, &ptr, max_sig_len)) { - goto err; + return -1; } size_t sig_len = max_sig_len; @@ -1711,7 +1709,7 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) { if (ssl3_protocol_version(ssl) == SSL3_VERSION) { if (ssl->cert->key_method != NULL) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY); - goto err; + return -1; } uint8_t digest[EVP_MAX_MD_SIZE]; @@ -1719,7 +1717,7 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) { if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(&hs->transcript, digest, &digest_len, hs->new_session, signature_algorithm)) { - goto err; + return -1; } EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL); @@ -1728,7 +1726,7 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) { EVP_PKEY_sign(pctx, ptr, &sig_len, digest, digest_len); EVP_PKEY_CTX_free(pctx); if (!ok) { - goto err; + return -1; } } else { switch (ssl_private_key_sign(hs, ptr, &sig_len, max_sig_len, @@ -1738,25 +1736,21 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) { case ssl_private_key_success: break; case ssl_private_key_failure: - goto err; + return -1; case ssl_private_key_retry: ssl->rwstate = SSL_PRIVATE_KEY_OPERATION; - goto err; + return -1; } } if (!CBB_did_write(&child, sig_len) || - !ssl_add_message_cbb(ssl, &cbb)) { - goto err; + !ssl_add_message_cbb(ssl, cbb.get())) { + return -1; } /* The handshake buffer is no longer necessary. */ SSL_TRANSCRIPT_free_buffer(&hs->transcript); return 1; - -err: - CBB_cleanup(&cbb); - return -1; } static int ssl3_send_next_proto(SSL_HANDSHAKE *hs) { diff --git a/ssl/handshake_server.c b/ssl/handshake_server.cc similarity index 97% rename from ssl/handshake_server.c rename to ssl/handshake_server.cc index 64abd5d2..ee5358c4 100644 --- a/ssl/handshake_server.c +++ b/ssl/handshake_server.cc @@ -800,9 +800,6 @@ static int ssl3_select_certificate(SSL_HANDSHAKE *hs) { static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - int ret = -1; - SSL_SESSION *session = NULL; - SSL_CLIENT_HELLO client_hello; if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg, ssl->init_num)) { @@ -811,49 +808,52 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { /* Determine whether we are doing session resumption. */ int tickets_supported = 0, renew_ticket = 0; - switch (ssl_get_prev_session(ssl, &session, &tickets_supported, &renew_ticket, - &client_hello)) { + /* TODO(davidben): Switch |ssl_get_prev_session| to take a |bssl::UniquePtr| + * output and simplify this. */ + SSL_SESSION *session_raw = nullptr; + auto session_ret = ssl_get_prev_session(ssl, &session_raw, &tickets_supported, + &renew_ticket, &client_hello); + bssl::UniquePtr session(session_raw); + switch (session_ret) { case ssl_session_success: break; case ssl_session_error: - goto err; + return -1; case ssl_session_retry: ssl->rwstate = SSL_PENDING_SESSION; - goto err; + return -1; case ssl_session_ticket_retry: ssl->rwstate = SSL_PENDING_TICKET; - goto err; + return -1; } - if (session != NULL) { + if (session) { if (session->extended_master_secret && !hs->extended_master_secret) { /* A ClientHello without EMS that attempts to resume a session with EMS * is fatal to the connection. */ OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - goto err; + return -1; } - if (!ssl_session_is_resumable(hs, session) || + if (!ssl_session_is_resumable(hs, session.get()) || /* If the client offers the EMS extension, but the previous session * didn't use it, then negotiate a new session. */ hs->extended_master_secret != session->extended_master_secret) { - SSL_SESSION_free(session); - session = NULL; + session.reset(); } } - if (session != NULL) { + if (session) { /* Use the old session. */ hs->ticket_expected = renew_ticket; - ssl->session = session; - session = NULL; + ssl->session = session.release(); ssl->s3->session_reused = 1; } else { hs->ticket_expected = tickets_supported; ssl_set_session(ssl, NULL); if (!ssl_get_new_session(hs, 1 /* server */)) { - goto err; + return -1; } /* Clear the session ID if we want the session to be single-use. */ @@ -867,7 +867,7 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { /* Connection rejected for DOS reasons. */ OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - goto err; + return -1; } if (ssl->session == NULL) { @@ -879,7 +879,7 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname); if (hs->new_session->tlsext_hostname == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - goto err; + return -1; } } @@ -907,7 +907,7 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { uint8_t alert = SSL_AD_DECODE_ERROR; if (!ssl_negotiate_alpn(hs, &alert, &client_hello)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); - goto err; + return -1; } /* Now that all parameters are known, initialize the handshake hash and hash @@ -916,7 +916,7 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { hs->new_cipher->algorithm_prf) || !ssl_hash_current_message(hs)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - goto err; + return -1; } /* Release the handshake buffer if client authentication isn't required. */ @@ -924,11 +924,7 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { SSL_TRANSCRIPT_free_buffer(&hs->transcript); } - ret = 1; - -err: - SSL_SESSION_free(session); - return ret; + return 1; } static int ssl3_send_server_hello(SSL_HANDSHAKE *hs) { @@ -988,32 +984,30 @@ static int ssl3_send_server_hello(SSL_HANDSHAKE *hs) { static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - int ret = -1; - CBB cbb; - CBB_zero(&cbb); + bssl::ScopedCBB cbb; if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) { if (!ssl_has_certificate(ssl)) { OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET); - goto err; + return -1; } if (!ssl3_output_cert_chain(ssl)) { - goto err; + return -1; } if (hs->certificate_status_expected) { CBB body, ocsp_response; - if (!ssl->method->init_message(ssl, &cbb, &body, + if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CERTIFICATE_STATUS) || !CBB_add_u8(&body, TLSEXT_STATUSTYPE_ocsp) || !CBB_add_u24_length_prefixed(&body, &ocsp_response) || !CBB_add_bytes(&ocsp_response, CRYPTO_BUFFER_data(ssl->cert->ocsp_response), CRYPTO_BUFFER_len(ssl->cert->ocsp_response)) || - !ssl_add_message_cbb(ssl, &cbb)) { + !ssl_add_message_cbb(ssl, cbb.get())) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - goto err; + return -1; } } } @@ -1027,20 +1021,20 @@ static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) { /* Pre-allocate enough room to comfortably fit an ECDHE public key. Prepend * the client and server randoms for the signing transcript. */ CBB child; - if (!CBB_init(&cbb, SSL3_RANDOM_SIZE * 2 + 128) || - !CBB_add_bytes(&cbb, ssl->s3->client_random, SSL3_RANDOM_SIZE) || - !CBB_add_bytes(&cbb, ssl->s3->server_random, SSL3_RANDOM_SIZE)) { - goto err; + if (!CBB_init(cbb.get(), SSL3_RANDOM_SIZE * 2 + 128) || + !CBB_add_bytes(cbb.get(), ssl->s3->client_random, SSL3_RANDOM_SIZE) || + !CBB_add_bytes(cbb.get(), ssl->s3->server_random, SSL3_RANDOM_SIZE)) { + return -1; } /* PSK ciphers begin with an identity hint. */ if (alg_a & SSL_aPSK) { size_t len = (ssl->psk_identity_hint == NULL) ? 0 : strlen(ssl->psk_identity_hint); - if (!CBB_add_u16_length_prefixed(&cbb, &child) || + if (!CBB_add_u16_length_prefixed(cbb.get(), &child) || !CBB_add_bytes(&child, (const uint8_t *)ssl->psk_identity_hint, len)) { - goto err; + return -1; } } @@ -1050,32 +1044,28 @@ static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) { if (!tls1_get_shared_group(hs, &group_id)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - goto err; - } + return -1; + } hs->new_session->group_id = group_id; /* Set up ECDH, generate a key, and emit the public half. */ if (!SSL_ECDH_CTX_init(&hs->ecdh_ctx, group_id) || - !CBB_add_u8(&cbb, NAMED_CURVE_TYPE) || - !CBB_add_u16(&cbb, group_id) || - !CBB_add_u8_length_prefixed(&cbb, &child) || + !CBB_add_u8(cbb.get(), NAMED_CURVE_TYPE) || + !CBB_add_u16(cbb.get(), group_id) || + !CBB_add_u8_length_prefixed(cbb.get(), &child) || !SSL_ECDH_CTX_offer(&hs->ecdh_ctx, &child)) { - goto err; + return -1; } } else { assert(alg_k & SSL_kPSK); } - if (!CBB_finish(&cbb, &hs->server_params, &hs->server_params_len)) { - goto err; + if (!CBB_finish(cbb.get(), &hs->server_params, &hs->server_params_len)) { + return -1; } } - ret = 1; - -err: - CBB_cleanup(&cbb); - return ret; + return 1; } static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) { @@ -1348,7 +1338,7 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) { /* Allocate a buffer large enough for an RSA decryption. */ const size_t rsa_size = EVP_PKEY_size(hs->local_pubkey); - decrypt_buf = OPENSSL_malloc(rsa_size); + decrypt_buf = (uint8_t *)OPENSSL_malloc(rsa_size); if (decrypt_buf == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; @@ -1379,7 +1369,7 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) { /* Prepare a random premaster, to be used on invalid padding. See RFC 5246, * section 7.4.7.1. */ premaster_secret_len = SSL_MAX_MASTER_KEY_LENGTH; - premaster_secret = OPENSSL_malloc(premaster_secret_len); + premaster_secret = (uint8_t *)OPENSSL_malloc(premaster_secret_len); if (premaster_secret == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; @@ -1476,7 +1466,7 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) { /* In plain PSK, other_secret is a block of 0s with the same length as the * pre-shared key. */ premaster_secret_len = psk_len; - premaster_secret = OPENSSL_malloc(premaster_secret_len); + premaster_secret = (uint8_t *)OPENSSL_malloc(premaster_secret_len); if (premaster_secret == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err;