Commit 9f48bbac authored by Emilia Kasper's avatar Emilia Kasper
Browse files

Reorganize SSL test structures



Move custom server and client options from the test dictionary to an
"extra" section of each server/client. Rename test expectations to say
"Expected".

This is a big but straightforward change. Primarily, this allows us to
specify multiple server and client contexts without redefining the
custom options for each of them. For example, instead of
"ServerNPNProtocols", "Server2NPNProtocols", "ResumeServerNPNProtocols",
we now have, "NPNProtocols".

This simplifies writing resumption and SNI tests. The first application
will be resumption tests for NPN and ALPN.

Regrouping the options also makes it clearer which options apply to the
server, which apply to the client, which configure the test, and which
are test expectations.

Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
parent a4a18b2f
Loading
Loading
Loading
Loading
+66 −37
Original line number Original line Diff line number Diff line
@@ -45,7 +45,22 @@ An example test input looks like this:
    }
    }
```
```


The test section supports the following options:
The test section supports the following options

### Test mode

* Method - the method to test. One of DTLS or TLS.

* HandshakeMode - which handshake flavour to test:
  - Simple - plain handshake (default)
  - Resume - test resumption
  - (Renegotiate - test renegotiation, not yet implemented)

When HandshakeMode is Resume or Renegotiate, the original handshake is expected
to succeed. All configured test expectations are verified against the second
handshake.

### Test expectations


* ExpectedResult - expected handshake outcome. One of
* ExpectedResult - expected handshake outcome. One of
  - Success - handshake success
  - Success - handshake success
@@ -53,54 +68,22 @@ The test section supports the following options:
  - ClientFail - clientside handshake failure
  - ClientFail - clientside handshake failure
  - InternalError - some other error
  - InternalError - some other error


* ClientAlert, ServerAlert - expected alert. See `ssl_test_ctx.c` for known
* ExpectedClientAlert, ExpectedServerAlert - expected alert. See
  values.
  `ssl_test_ctx.c` for known values.


* Protocol - expected negotiated protocol. One of
* ExpectedProtocol - expected negotiated protocol. One of
  SSLv3, TLSv1, TLSv1.1, TLSv1.2.
  SSLv3, TLSv1, TLSv1.1, TLSv1.2.


* ClientVerifyCallback - the client's custom certificate verify callback.
  Used to test callback behaviour. One of
  - None - no custom callback (default)
  - AcceptAll - accepts all certificates.
  - RejectAll - rejects all certificates.

* Method - the method to test. One of DTLS or TLS.

* ServerName - the server the client should attempt to connect to. One of
  - None - do not use SNI (default)
  - server1 - the initial context
  - server2 - the secondary context
  - invalid - an unknown context

* ServerNameCallback - the SNI switching callback to use
  - None - no callback (default)
  - IgnoreMismatch - continue the handshake on SNI mismatch
  - RejectMismatch - abort the handshake on SNI mismatch

* SessionTicketExpected - whether or not a session ticket is expected
* SessionTicketExpected - whether or not a session ticket is expected
  - Ignore - do not check for a session ticket (default)
  - Ignore - do not check for a session ticket (default)
  - Yes - a session ticket is expected
  - Yes - a session ticket is expected
  - No - a session ticket is not expected
  - No - a session ticket is not expected
  - Broken - a special test case where the session ticket callback does not
    initialize crypto

* HandshakeMode - which handshake flavour to test:
  - Simple - plain handshake (default)
  - Resume - test resumption
  - (Renegotiate - test renegotiation, not yet implemented)


* ResumptionExpected - whether or not resumption is expected (Resume mode only)
* ResumptionExpected - whether or not resumption is expected (Resume mode only)
  - Yes - resumed handshake
  - Yes - resumed handshake
  - No - full handshake (default)
  - No - full handshake (default)


When HandshakeMode is Resume or Renegotiate, the original handshake is expected
* ExpectedNPNProtocol, ExpectedALPNProtocol - NPN and ALPN expectations.
to succeed. All configured test expectations are verified against the second handshake.

* ServerNPNProtocols, Server2NPNProtocols, ClientNPNProtocols, ExpectedNPNProtocol,
  ServerALPNProtocols, Server2ALPNProtocols, ClientALPNProtocols, ExpectedALPNProtocol -
  NPN and ALPN settings. Server and client protocols can be specified as a comma-separated list,
  and a callback with the recommended behaviour will be installed automatically.


## Configuring the client and server
## Configuring the client and server


@@ -132,6 +115,52 @@ The following sections may optionally be defined:
  whenever HandshakeMode is Resume. If the resume_client section is not present,
  whenever HandshakeMode is Resume. If the resume_client section is not present,
  then the configuration matches client.
  then the configuration matches client.


### Configuring callbacks and additional options

Additional handshake settings can be configured in the `extra` section of each
client and server:

```
client => {
    "CipherString" => "DEFAULT",
    extra => {
        "ServerName" => "server2",
    }
}
```

#### Supported client-side options

* ClientVerifyCallback - the client's custom certificate verify callback.
  Used to test callback behaviour. One of
  - None - no custom callback (default)
  - AcceptAll - accepts all certificates.
  - RejectAll - rejects all certificates.

* ServerName - the server the client should attempt to connect to. One of
  - None - do not use SNI (default)
  - server1 - the initial context
  - server2 - the secondary context
  - invalid - an unknown context

#### Supported server-side options

* ServerNameCallback - the SNI switching callback to use
  - None - no callback (default)
  - IgnoreMismatch - continue the handshake on SNI mismatch
  - RejectMismatch - abort the handshake on SNI mismatch

* BrokenSessionTicket - a special test case where the session ticket callback
  does not initialize crypto.
  - No (default)
  - Yes

#### Mutually supported options

* NPNProtocols, ALPNProtocols - NPN and ALPN settings. Server and client
  protocols can be specified as a comma-separated list, and a callback with the
  recommended behaviour will be installed automatically.

### Default server and client configurations
### Default server and client configurations


The default server certificate and CA files are added to the configurations
The default server certificate and CA files are added to the configurations
+2 −1
Original line number Original line Diff line number Diff line
@@ -46,7 +46,8 @@ sub print_templates {
        if (defined $test->{"server2"}) {
        if (defined $test->{"server2"}) {
            $test->{"server2"} = { (%ssltests::base_server, %{$test->{"server2"}}) };
            $test->{"server2"} = { (%ssltests::base_server, %{$test->{"server2"}}) };
        } else {
        } else {
            if (defined $test->{"test"}->{"ServerNameCallback"}) {
            if ($test->{"server"}->{"extra"} &&
                defined $test->{"server"}->{"extra"}->{"ServerNameCallback"}) {
                # Default is the same as server.
                # Default is the same as server.
                $test->{"reuse_server2"} = 1;
                $test->{"reuse_server2"} = 1;
            }
            }
+24 −24
Original line number Original line Diff line number Diff line
@@ -269,7 +269,7 @@ static int server_alpn_cb(SSL *s, const unsigned char **out,
 */
 */
static void configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
static void configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
                                    SSL_CTX *client_ctx,
                                    SSL_CTX *client_ctx,
                                    const SSL_TEST_CTX *test_ctx,
                                    const SSL_TEST_EXTRA_CONF *extra,
                                    CTX_DATA *server_ctx_data,
                                    CTX_DATA *server_ctx_data,
                                    CTX_DATA *server2_ctx_data,
                                    CTX_DATA *server2_ctx_data,
                                    CTX_DATA *client_ctx_data)
                                    CTX_DATA *client_ctx_data)
@@ -277,7 +277,7 @@ static void configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
    unsigned char *ticket_keys;
    unsigned char *ticket_keys;
    size_t ticket_key_len;
    size_t ticket_key_len;


    switch (test_ctx->client_verify_callback) {
    switch (extra->client.verify_callback) {
    case SSL_TEST_VERIFY_ACCEPT_ALL:
    case SSL_TEST_VERIFY_ACCEPT_ALL:
        SSL_CTX_set_cert_verify_callback(client_ctx, &verify_accept_cb,
        SSL_CTX_set_cert_verify_callback(client_ctx, &verify_accept_cb,
                                         NULL);
                                         NULL);
@@ -291,7 +291,7 @@ static void configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
    }
    }


    /* link the two contexts for SNI purposes */
    /* link the two contexts for SNI purposes */
    switch (test_ctx->servername_callback) {
    switch (extra->server.servername_callback) {
    case SSL_TEST_SERVERNAME_IGNORE_MISMATCH:
    case SSL_TEST_SERVERNAME_IGNORE_MISMATCH:
        SSL_CTX_set_tlsext_servername_callback(server_ctx, servername_ignore_cb);
        SSL_CTX_set_tlsext_servername_callback(server_ctx, servername_ignore_cb);
        SSL_CTX_set_tlsext_servername_arg(server_ctx, server2_ctx);
        SSL_CTX_set_tlsext_servername_arg(server_ctx, server2_ctx);
@@ -313,49 +313,49 @@ static void configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
        SSL_CTX_set_tlsext_ticket_key_cb(server2_ctx,
        SSL_CTX_set_tlsext_ticket_key_cb(server2_ctx,
                                         do_not_call_session_ticket_cb);
                                         do_not_call_session_ticket_cb);


    if (test_ctx->session_ticket_expected == SSL_TEST_SESSION_TICKET_BROKEN) {
    if (extra->server.broken_session_ticket) {
        SSL_CTX_set_tlsext_ticket_key_cb(server_ctx, broken_session_ticket_cb);
        SSL_CTX_set_tlsext_ticket_key_cb(server_ctx, broken_session_ticket_cb);
    }
    }
#ifndef OPENSSL_NO_NEXTPROTONEG
#ifndef OPENSSL_NO_NEXTPROTONEG
    if (test_ctx->server_npn_protocols != NULL) {
    if (extra->server.npn_protocols != NULL) {
        parse_protos(test_ctx->server_npn_protocols,
        parse_protos(extra->server.npn_protocols,
                     &server_ctx_data->npn_protocols,
                     &server_ctx_data->npn_protocols,
                     &server_ctx_data->npn_protocols_len);
                     &server_ctx_data->npn_protocols_len);
        SSL_CTX_set_next_protos_advertised_cb(server_ctx, server_npn_cb,
        SSL_CTX_set_next_protos_advertised_cb(server_ctx, server_npn_cb,
                                              server_ctx_data);
                                              server_ctx_data);
    }
    }
    if (test_ctx->server2_npn_protocols != NULL) {
    if (extra->server2.npn_protocols != NULL) {
        parse_protos(test_ctx->server2_npn_protocols,
        parse_protos(extra->server2.npn_protocols,
                     &server2_ctx_data->npn_protocols,
                     &server2_ctx_data->npn_protocols,
                     &server2_ctx_data->npn_protocols_len);
                     &server2_ctx_data->npn_protocols_len);
        OPENSSL_assert(server2_ctx != NULL);
        OPENSSL_assert(server2_ctx != NULL);
        SSL_CTX_set_next_protos_advertised_cb(server2_ctx, server_npn_cb,
        SSL_CTX_set_next_protos_advertised_cb(server2_ctx, server_npn_cb,
                                              server2_ctx_data);
                                              server2_ctx_data);
    }
    }
    if (test_ctx->client_npn_protocols != NULL) {
    if (extra->client.npn_protocols != NULL) {
        parse_protos(test_ctx->client_npn_protocols,
        parse_protos(extra->client.npn_protocols,
                     &client_ctx_data->npn_protocols,
                     &client_ctx_data->npn_protocols,
                     &client_ctx_data->npn_protocols_len);
                     &client_ctx_data->npn_protocols_len);
        SSL_CTX_set_next_proto_select_cb(client_ctx, client_npn_cb,
        SSL_CTX_set_next_proto_select_cb(client_ctx, client_npn_cb,
                                         client_ctx_data);
                                         client_ctx_data);
    }
    }
    if (test_ctx->server_alpn_protocols != NULL) {
    if (extra->server.alpn_protocols != NULL) {
        parse_protos(test_ctx->server_alpn_protocols,
        parse_protos(extra->server.alpn_protocols,
                     &server_ctx_data->alpn_protocols,
                     &server_ctx_data->alpn_protocols,
                     &server_ctx_data->alpn_protocols_len);
                     &server_ctx_data->alpn_protocols_len);
        SSL_CTX_set_alpn_select_cb(server_ctx, server_alpn_cb, server_ctx_data);
        SSL_CTX_set_alpn_select_cb(server_ctx, server_alpn_cb, server_ctx_data);
    }
    }
    if (test_ctx->server2_alpn_protocols != NULL) {
    if (extra->server2.alpn_protocols != NULL) {
        OPENSSL_assert(server2_ctx != NULL);
        OPENSSL_assert(server2_ctx != NULL);
        parse_protos(test_ctx->server2_alpn_protocols,
        parse_protos(extra->server2.alpn_protocols,
                     &server2_ctx_data->alpn_protocols,
                     &server2_ctx_data->alpn_protocols,
                     &server2_ctx_data->alpn_protocols_len);
                     &server2_ctx_data->alpn_protocols_len);
        SSL_CTX_set_alpn_select_cb(server2_ctx, server_alpn_cb, server2_ctx_data);
        SSL_CTX_set_alpn_select_cb(server2_ctx, server_alpn_cb, server2_ctx_data);
    }
    }
    if (test_ctx->client_alpn_protocols != NULL) {
    if (extra->client.alpn_protocols != NULL) {
        unsigned char *alpn_protos = NULL;
        unsigned char *alpn_protos = NULL;
        size_t alpn_protos_len;
        size_t alpn_protos_len;
        parse_protos(test_ctx->client_alpn_protocols,
        parse_protos(extra->client.alpn_protocols,
                     &alpn_protos, &alpn_protos_len);
                     &alpn_protos, &alpn_protos_len);
        /* Reversed return value convention... */
        /* Reversed return value convention... */
        OPENSSL_assert(SSL_CTX_set_alpn_protos(client_ctx, alpn_protos,
        OPENSSL_assert(SSL_CTX_set_alpn_protos(client_ctx, alpn_protos,
@@ -377,11 +377,11 @@ static void configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,


/* Configure per-SSL callbacks and other properties. */
/* Configure per-SSL callbacks and other properties. */
static void configure_handshake_ssl(SSL *server, SSL *client,
static void configure_handshake_ssl(SSL *server, SSL *client,
                                    const SSL_TEST_CTX *test_ctx)
                                    const SSL_TEST_EXTRA_CONF *extra)
{
{
    if (test_ctx->servername != SSL_TEST_SERVERNAME_NONE)
    if (extra->client.servername != SSL_TEST_SERVERNAME_NONE)
        SSL_set_tlsext_host_name(client,
        SSL_set_tlsext_host_name(client,
                                 ssl_servername_name(test_ctx->servername));
                                 ssl_servername_name(extra->client.servername));
}
}




@@ -518,7 +518,7 @@ static char *dup_str(const unsigned char *in, size_t len)


static HANDSHAKE_RESULT *do_handshake_internal(
static HANDSHAKE_RESULT *do_handshake_internal(
    SSL_CTX *server_ctx, SSL_CTX *server2_ctx, SSL_CTX *client_ctx,
    SSL_CTX *server_ctx, SSL_CTX *server2_ctx, SSL_CTX *client_ctx,
    const SSL_TEST_CTX *test_ctx, SSL_SESSION *session_in,
    const SSL_TEST_EXTRA_CONF *extra, SSL_SESSION *session_in,
    SSL_SESSION **session_out)
    SSL_SESSION **session_out)
{
{
    SSL *server, *client;
    SSL *server, *client;
@@ -542,14 +542,14 @@ static HANDSHAKE_RESULT *do_handshake_internal(
    memset(&server2_ctx_data, 0, sizeof(server2_ctx_data));
    memset(&server2_ctx_data, 0, sizeof(server2_ctx_data));
    memset(&client_ctx_data, 0, sizeof(client_ctx_data));
    memset(&client_ctx_data, 0, sizeof(client_ctx_data));


    configure_handshake_ctx(server_ctx, server2_ctx, client_ctx, test_ctx,
    configure_handshake_ctx(server_ctx, server2_ctx, client_ctx, extra,
                            &server_ctx_data, &server2_ctx_data, &client_ctx_data);
                            &server_ctx_data, &server2_ctx_data, &client_ctx_data);


    server = SSL_new(server_ctx);
    server = SSL_new(server_ctx);
    client = SSL_new(client_ctx);
    client = SSL_new(client_ctx);
    OPENSSL_assert(server != NULL && client != NULL);
    OPENSSL_assert(server != NULL && client != NULL);


    configure_handshake_ssl(server, client, test_ctx);
    configure_handshake_ssl(server, client, extra);
    if (session_in != NULL) {
    if (session_in != NULL) {
        /* In case we're testing resumption without tickets. */
        /* In case we're testing resumption without tickets. */
        OPENSSL_assert(SSL_CTX_add_session(server_ctx, session_in));
        OPENSSL_assert(SSL_CTX_add_session(server_ctx, session_in));
@@ -689,7 +689,7 @@ HANDSHAKE_RESULT *do_handshake(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
    SSL_SESSION *session = NULL;
    SSL_SESSION *session = NULL;


    result = do_handshake_internal(server_ctx, server2_ctx, client_ctx,
    result = do_handshake_internal(server_ctx, server2_ctx, client_ctx,
                                   test_ctx, NULL, &session);
                                   &test_ctx->extra, NULL, &session);
    if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_SIMPLE)
    if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_SIMPLE)
        goto end;
        goto end;


@@ -703,7 +703,7 @@ HANDSHAKE_RESULT *do_handshake(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
    HANDSHAKE_RESULT_free(result);
    HANDSHAKE_RESULT_free(result);
    /* We don't support SNI on second handshake yet, so server2_ctx is NULL. */
    /* We don't support SNI on second handshake yet, so server2_ctx is NULL. */
    result = do_handshake_internal(resume_server_ctx, NULL, resume_client_ctx,
    result = do_handshake_internal(resume_server_ctx, NULL, resume_client_ctx,
                                   test_ctx, session, NULL);
                                   &test_ctx->resume_extra, session, NULL);
 end:
 end:
    SSL_SESSION_free(session);
    SSL_SESSION_free(session);
    return result;
    return result;
+1 −1
Original line number Original line Diff line number Diff line
@@ -46,7 +46,7 @@ CipherString = DEFAULT
VerifyMode = Peer
VerifyMode = Peer


[test-1]
[test-1]
ClientAlert = UnknownCA
ExpectedClientAlert = UnknownCA
ExpectedResult = ClientFail
ExpectedResult = ClientFail


+1 −1
Original line number Original line Diff line number Diff line
@@ -28,7 +28,7 @@ our @tests = (
        },
        },
        test   => {
        test   => {
          "ExpectedResult" => "ClientFail",
          "ExpectedResult" => "ClientFail",
          "ClientAlert" => "UnknownCA",
          "ExpectedClientAlert" => "UnknownCA",
        },
        },
    },
    },
);
);
Loading