From: Matt Caswell Date: Tue, 27 Sep 2016 10:50:43 +0000 (+0100) Subject: Extend the renegotiation tests X-Git-Tag: OpenSSL_1_1_0c~110 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=f1522af442d4154db28928ab178c258f07ed4c5e;p=oweals%2Fopenssl.git Extend the renegotiation tests Add the ability to test both server initiated and client initiated reneg. Reviewed-by: Rich Salz (cherry picked from commit fe7dd5534176d1b04be046fcbaad24430c8727e0) --- diff --git a/test/README.ssltest.md b/test/README.ssltest.md index ca6edf54d6..e28d4b0d47 100644 --- a/test/README.ssltest.md +++ b/test/README.ssltest.md @@ -38,7 +38,8 @@ The test section supports the following options * HandshakeMode - which handshake flavour to test: - Simple - plain handshake (default) - Resume - test resumption - - Renegotiate - test renegotiation + - RenegotiateServer - test server initiated renegotiation + - RenegotiateClient - test client initiated renegotiation When HandshakeMode is Resume or Renegotiate, the original handshake is expected to succeed. All configured test expectations are verified against the second diff --git a/test/handshake_helper.c b/test/handshake_helper.c index dcc9d8dd22..c14d8e38c4 100644 --- a/test/handshake_helper.c +++ b/test/handshake_helper.c @@ -583,30 +583,55 @@ static void do_app_data_step(PEER *peer) } } -static void do_reneg_setup_step(PEER *peer) +static void do_reneg_setup_step(const SSL_TEST_CTX *test_ctx, 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); + TEST_check(test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_SERVER + || test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_CLIENT); + + /* Check if we are the peer that is going to initiate */ + if ((test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_SERVER + && SSL_is_server(peer->ssl)) + || (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_CLIENT + && !SSL_is_server(peer->ssl))) { /* - * 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 we already asked for a renegotiation then fall through to the + * SSL_read() below. */ - if (peer->status == PEER_RETRY) - peer->status = PEER_SUCCESS; - return; + if (!SSL_renegotiate_pending(peer->ssl)) { + /* + * If we are the client we will always attempt to resume the + * session. The server may or may not resume dependant on the + * setting of SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION + */ + if (SSL_is_server(peer->ssl)) + ret = SSL_renegotiate(peer->ssl); + else + ret = SSL_renegotiate_abbreviated(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 peer 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 status is PEER_SUCCESS then we are the server and we have + * successfully sent the HelloRequest. We need to continue to wait + * until the handshake arrives from the client. + */ + if (peer->status == PEER_RETRY) + peer->status = PEER_SUCCESS; + else if (peer->status == PEER_SUCCESS) + peer->status = PEER_RETRY; + return; + } } /* @@ -616,15 +641,21 @@ static void do_reneg_setup_step(PEER *peer) */ ret = SSL_read(peer->ssl, &buf, sizeof(buf)); if (ret >= 0) { - /* We're not actually expecting data - we're expect a reneg to start */ + /* + * We're not actually expecting data - we're expecting 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)) { + if (error != SSL_ERROR_WANT_READ) { peer->status = PEER_ERROR; return; } + /* If we're no in init yet then we're not done with setup yet */ + if (!SSL_in_init(peer->ssl)) + return; } peer->status = PEER_SUCCESS; @@ -678,7 +709,8 @@ static connect_phase_t next_phase(const SSL_TEST_CTX *test_ctx, { switch (phase) { case HANDSHAKE: - if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEGOTIATE) + if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_SERVER + || test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_CLIENT) return RENEG_APPLICATION_DATA; return APPLICATION_DATA; case RENEG_APPLICATION_DATA: @@ -696,7 +728,8 @@ static connect_phase_t next_phase(const SSL_TEST_CTX *test_ctx, } } -static void do_connect_step(PEER *peer, connect_phase_t phase) +static void do_connect_step(const SSL_TEST_CTX *test_ctx, PEER *peer, + connect_phase_t phase) { switch (phase) { case HANDSHAKE: @@ -706,7 +739,7 @@ static void do_connect_step(PEER *peer, connect_phase_t phase) do_app_data_step(peer); break; case RENEG_SETUP: - do_reneg_setup_step(peer); + do_reneg_setup_step(test_ctx, peer); break; case RENEG_HANDSHAKE: do_handshake_step(peer); @@ -912,11 +945,11 @@ static HANDSHAKE_RESULT *do_handshake_internal( */ for(;;) { if (client_turn) { - do_connect_step(&client, phase); + do_connect_step(test_ctx, &client, phase); status = handshake_status(client.status, server.status, 1 /* client went last */); } else { - do_connect_step(&server, phase); + do_connect_step(test_ctx, &server, phase); status = handshake_status(server.status, client.status, 0 /* server went last */); } diff --git a/test/ssl-tests/17-renegotiate.conf b/test/ssl-tests/17-renegotiate.conf index 5ef4b0ac77..c47a9567dd 100644 --- a/test/ssl-tests/17-renegotiate.conf +++ b/test/ssl-tests/17-renegotiate.conf @@ -1,30 +1,114 @@ # Generated with generate_ssl_tests.pl -num_tests = 1 +num_tests = 4 -test-0 = 0-renegotiate +test-0 = 0-renegotiate-client-no-resume +test-1 = 1-renegotiate-client-resume +test-2 = 2-renegotiate-server-no-resume +test-3 = 3-renegotiate-server-resume # =========================================================== -[0-renegotiate] -ssl_conf = 0-renegotiate-ssl +[0-renegotiate-client-no-resume] +ssl_conf = 0-renegotiate-client-no-resume-ssl -[0-renegotiate-ssl] -server = 0-renegotiate-server -client = 0-renegotiate-client +[0-renegotiate-client-no-resume-ssl] +server = 0-renegotiate-client-no-resume-server +client = 0-renegotiate-client-no-resume-client -[0-renegotiate-server] +[0-renegotiate-client-no-resume-server] Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem CipherString = DEFAULT +Options = NoResumptionOnRenegotiation PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem -[0-renegotiate-client] +[0-renegotiate-client-no-resume-client] CipherString = DEFAULT VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer [test-0] ExpectedResult = Success -HandshakeMode = Renegotiate +HandshakeMode = RenegotiateClient Method = TLS +ResumptionExpected = No + + +# =========================================================== + +[1-renegotiate-client-resume] +ssl_conf = 1-renegotiate-client-resume-ssl + +[1-renegotiate-client-resume-ssl] +server = 1-renegotiate-client-resume-server +client = 1-renegotiate-client-resume-client + +[1-renegotiate-client-resume-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[1-renegotiate-client-resume-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-1] +ExpectedResult = Success +HandshakeMode = RenegotiateClient +Method = TLS +ResumptionExpected = Yes + + +# =========================================================== + +[2-renegotiate-server-no-resume] +ssl_conf = 2-renegotiate-server-no-resume-ssl + +[2-renegotiate-server-no-resume-ssl] +server = 2-renegotiate-server-no-resume-server +client = 2-renegotiate-server-no-resume-client + +[2-renegotiate-server-no-resume-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +Options = NoResumptionOnRenegotiation +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[2-renegotiate-server-no-resume-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-2] +ExpectedResult = Success +HandshakeMode = RenegotiateServer +Method = TLS +ResumptionExpected = No + + +# =========================================================== + +[3-renegotiate-server-resume] +ssl_conf = 3-renegotiate-server-resume-ssl + +[3-renegotiate-server-resume-ssl] +server = 3-renegotiate-server-resume-server +client = 3-renegotiate-server-resume-client + +[3-renegotiate-server-resume-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[3-renegotiate-server-resume-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-3] +ExpectedResult = Success +HandshakeMode = RenegotiateServer +Method = TLS +ResumptionExpected = Yes diff --git a/test/ssl-tests/17-renegotiate.conf.in b/test/ssl-tests/17-renegotiate.conf.in index 6cecd7ed21..a081617724 100644 --- a/test/ssl-tests/17-renegotiate.conf.in +++ b/test/ssl-tests/17-renegotiate.conf.in @@ -17,12 +17,50 @@ package ssltests; our @tests = ( { - name => "renegotiate", + name => "renegotiate-client-no-resume", + server => { + "Options" => "NoResumptionOnRenegotiation" + }, + client => {}, + test => { + "Method" => "TLS", + "HandshakeMode" => "RenegotiateClient", + "ResumptionExpected" => "No", + "ExpectedResult" => "Success" + } + }, + { + name => "renegotiate-client-resume", + server => {}, + client => {}, + test => { + "Method" => "TLS", + "HandshakeMode" => "RenegotiateClient", + "ResumptionExpected" => "Yes", + "ExpectedResult" => "Success" + } + }, + { + name => "renegotiate-server-no-resume", + server => { + "Options" => "NoResumptionOnRenegotiation" + }, + client => {}, + test => { + "Method" => "TLS", + "HandshakeMode" => "RenegotiateServer", + "ResumptionExpected" => "No", + "ExpectedResult" => "Success" + } + }, + { + name => "renegotiate-server-resume", server => {}, client => {}, test => { "Method" => "TLS", - "HandshakeMode" => "Renegotiate", + "HandshakeMode" => "RenegotiateServer", + "ResumptionExpected" => "Yes", "ExpectedResult" => "Success" } }, diff --git a/test/ssl_test_ctx.c b/test/ssl_test_ctx.c index ee2e8a1088..0a528d805b 100644 --- a/test/ssl_test_ctx.c +++ b/test/ssl_test_ctx.c @@ -339,7 +339,8 @@ IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CTX, test, expected_alpn_protocol) static const test_enum ssl_handshake_modes[] = { {"Simple", SSL_TEST_HANDSHAKE_SIMPLE}, {"Resume", SSL_TEST_HANDSHAKE_RESUME}, - {"Renegotiate", SSL_TEST_HANDSHAKE_RENEGOTIATE}, + {"RenegotiateServer", SSL_TEST_HANDSHAKE_RENEG_SERVER}, + {"RenegotiateClient", SSL_TEST_HANDSHAKE_RENEG_CLIENT}, }; __owur static int parse_handshake_mode(SSL_TEST_CTX *test_ctx, const char *value) diff --git a/test/ssl_test_ctx.h b/test/ssl_test_ctx.h index 73e223a2d5..14acaff6f7 100644 --- a/test/ssl_test_ctx.h +++ b/test/ssl_test_ctx.h @@ -56,7 +56,8 @@ typedef enum { typedef enum { SSL_TEST_HANDSHAKE_SIMPLE = 0, /* Default */ SSL_TEST_HANDSHAKE_RESUME, - SSL_TEST_HANDSHAKE_RENEGOTIATE + SSL_TEST_HANDSHAKE_RENEG_SERVER, + SSL_TEST_HANDSHAKE_RENEG_CLIENT } ssl_handshake_mode_t; typedef enum {