Commit e42c4544 authored by Matt Caswell's avatar Matt Caswell
Browse files

Add support for testing renegotiation



Reviewed-by: default avatarRich Salz <rsalz@openssl.org>
parent 2f97192c
Loading
Loading
Loading
Loading
+72 −5
Original line number Diff line number Diff line
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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.
+30 −0
Original line number Diff line number Diff line
# 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

+29 −0
Original line number Diff line number Diff line
# -*- 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"
        }
    },
);
+0 −1
Original line number Diff line number Diff line
@@ -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;