diff --git a/test/handshake_helper.c b/test/handshake_helper.c index 3cfee16b61ac5aed0b252f00f978f43cdb33ae9a..1c6ad487cb8bf32595817484ed9d2f14323f8146 100644 --- a/test/handshake_helper.c +++ b/test/handshake_helper.c @@ -583,6 +583,54 @@ static void do_app_data_step(PEER *peer) } } +static void do_reneg_setup_step(PEER *peer) +{ + int ret; + char buf; + + TEST_check(peer->status == PEER_RETRY); + /* We only support client initiated reneg at the moment */ + /* TODO: server side */ + if (!SSL_is_server(peer->ssl)) { + ret = SSL_renegotiate(peer->ssl); + if (!ret) { + peer->status = PEER_ERROR; + return; + } + do_handshake_step(peer); + /* + * If status is PEER_RETRY it means we're waiting on the server to + * continue the handshake. As far as setting up the renegotiation is + * concerned that is a success. The next step will continue the + * handshake to its conclusion. + */ + if (peer->status == PEER_RETRY) + peer->status = PEER_SUCCESS; + return; + } + + /* + * The SSL object is still expecting app data, even though it's going to + * get a handshake message. We try to read, and it should fail - after which + * we should be in a handshake + */ + ret = SSL_read(peer->ssl, &buf, sizeof(buf)); + if (ret >= 0) { + /* We're not actually expecting data - we're expect a reneg to start */ + peer->status = PEER_ERROR; + return; + } else { + int error = SSL_get_error(peer->ssl, ret); + if (error != SSL_ERROR_WANT_READ || !SSL_in_init(peer->ssl)) { + peer->status = PEER_ERROR; + return; + } + } + + peer->status = PEER_SUCCESS; +} + + /* * RFC 5246 says: * @@ -617,15 +665,27 @@ static void do_shutdown_step(PEER *peer) typedef enum { HANDSHAKE, + RENEG_APPLICATION_DATA, + RENEG_SETUP, + RENEG_HANDSHAKE, APPLICATION_DATA, SHUTDOWN, CONNECTION_DONE } connect_phase_t; -static connect_phase_t next_phase(connect_phase_t phase) +static connect_phase_t next_phase(const SSL_TEST_CTX *test_ctx, + connect_phase_t phase) { switch (phase) { case HANDSHAKE: + if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEGOTIATE) + return RENEG_APPLICATION_DATA; + return APPLICATION_DATA; + case RENEG_APPLICATION_DATA: + return RENEG_SETUP; + case RENEG_SETUP: + return RENEG_HANDSHAKE; + case RENEG_HANDSHAKE: return APPLICATION_DATA; case APPLICATION_DATA: return SHUTDOWN; @@ -644,6 +704,15 @@ static void do_connect_step(PEER *peer, connect_phase_t phase) case HANDSHAKE: do_handshake_step(peer); break; + case RENEG_APPLICATION_DATA: + do_app_data_step(peer); + break; + case RENEG_SETUP: + do_reneg_setup_step(peer); + break; + case RENEG_HANDSHAKE: + do_handshake_step(peer); + break; case APPLICATION_DATA: do_app_data_step(peer); break; @@ -857,7 +926,7 @@ static HANDSHAKE_RESULT *do_handshake_internal( switch (status) { case HANDSHAKE_SUCCESS: - phase = next_phase(phase); + phase = next_phase(test_ctx, phase); if (phase == CONNECTION_DONE) { ret->result = SSL_TEST_SUCCESS; goto err; @@ -945,11 +1014,9 @@ HANDSHAKE_RESULT *do_handshake(SSL_CTX *server_ctx, SSL_CTX *server2_ctx, result = do_handshake_internal(server_ctx, server2_ctx, client_ctx, test_ctx, &test_ctx->extra, NULL, &session); - if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_SIMPLE) + if (test_ctx->handshake_mode != SSL_TEST_HANDSHAKE_RESUME) goto end; - TEST_check(test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RESUME); - if (result->result != SSL_TEST_SUCCESS) { result->result = SSL_TEST_FIRST_HANDSHAKE_FAILED; goto end; diff --git a/test/recipes/80-test_ssl_new.t b/test/recipes/80-test_ssl_new.t index 47eab18a95b4423cc55162ae0103a246b92758a5..d496f21ecd9025348c528caa0c618495a7ada722 100644 --- a/test/recipes/80-test_ssl_new.t +++ b/test/recipes/80-test_ssl_new.t @@ -29,7 +29,7 @@ map { s/\.in// } @conf_files; # We hard-code the number of tests to double-check that the globbing above # finds all files as expected. -plan tests => 16; # = scalar @conf_srcs +plan tests => 17; # = scalar @conf_srcs # Some test results depend on the configuration of enabled protocols. We only # verify generated sources in the default configuration. diff --git a/test/ssl-tests/17-renegotiate.conf b/test/ssl-tests/17-renegotiate.conf new file mode 100644 index 0000000000000000000000000000000000000000..5ef4b0ac77944900dce7d8a28cf1816035f958ce --- /dev/null +++ b/test/ssl-tests/17-renegotiate.conf @@ -0,0 +1,30 @@ +# Generated with generate_ssl_tests.pl + +num_tests = 1 + +test-0 = 0-renegotiate +# =========================================================== + +[0-renegotiate] +ssl_conf = 0-renegotiate-ssl + +[0-renegotiate-ssl] +server = 0-renegotiate-server +client = 0-renegotiate-client + +[0-renegotiate-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[0-renegotiate-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-0] +ExpectedResult = Success +HandshakeMode = Renegotiate +Method = TLS + + diff --git a/test/ssl-tests/17-renegotiate.conf.in b/test/ssl-tests/17-renegotiate.conf.in new file mode 100644 index 0000000000000000000000000000000000000000..6cecd7ed21261a4480c164bd921fc672b213eb72 --- /dev/null +++ b/test/ssl-tests/17-renegotiate.conf.in @@ -0,0 +1,29 @@ +# -*- mode: perl; -*- +# Copyright 2016-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +## Test Renegotiation + +use strict; +use warnings; + +package ssltests; + + +our @tests = ( + { + name => "renegotiate", + server => {}, + client => {}, + test => { + "Method" => "TLS", + "HandshakeMode" => "Renegotiate", + "ExpectedResult" => "Success" + } + }, +); diff --git a/test/ssl_test_ctx.h b/test/ssl_test_ctx.h index c8c66d6d709a4a1767d32c4bd16c8e3ffcb6bfcf..73e223a2d59379740a86488191a503d7c698ebc4 100644 --- a/test/ssl_test_ctx.h +++ b/test/ssl_test_ctx.h @@ -56,7 +56,6 @@ typedef enum { typedef enum { SSL_TEST_HANDSHAKE_SIMPLE = 0, /* Default */ SSL_TEST_HANDSHAKE_RESUME, - /* Not yet implemented */ SSL_TEST_HANDSHAKE_RENEGOTIATE } ssl_handshake_mode_t;