handshake_helper.c 24.8 KB
Newer Older
E
Emilia Kasper 已提交
1 2 3
/*
 * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
 *
R
Rich Salz 已提交
4 5 6
 * 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
E
Emilia Kasper 已提交
7 8 9 10 11 12
 * https://www.openssl.org/source/license.html
 */

#include <string.h>

#include <openssl/bio.h>
13
#include <openssl/x509_vfy.h>
E
Emilia Kasper 已提交
14 15 16
#include <openssl/ssl.h>

#include "handshake_helper.h"
E
Emilia Kasper 已提交
17
#include "testutil.h"
E
Emilia Kasper 已提交
18

19 20
HANDSHAKE_RESULT *HANDSHAKE_RESULT_new()
{
E
Emilia Kasper 已提交
21 22
    HANDSHAKE_RESULT *ret = OPENSSL_zalloc(sizeof(*ret));
    TEST_check(ret != NULL);
23 24 25 26 27
    return ret;
}

void HANDSHAKE_RESULT_free(HANDSHAKE_RESULT *result)
{
28 29
    if (result == NULL)
        return;
30 31 32 33 34 35 36
    OPENSSL_free(result->client_npn_negotiated);
    OPENSSL_free(result->server_npn_negotiated);
    OPENSSL_free(result->client_alpn_negotiated);
    OPENSSL_free(result->server_alpn_negotiated);
    OPENSSL_free(result);
}

E
Emilia Kasper 已提交
37 38 39 40 41 42 43 44
/*
 * Since there appears to be no way to extract the sent/received alert
 * from the SSL object directly, we use the info callback and stash
 * the result in ex_data.
 */
typedef struct handshake_ex_data {
    int alert_sent;
    int alert_received;
T
Todd Short 已提交
45
    int session_ticket_do_not_call;
46
    ssl_servername_t servername;
E
Emilia Kasper 已提交
47 48
} HANDSHAKE_EX_DATA;

49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
typedef struct ctx_data {
    unsigned char *npn_protocols;
    size_t npn_protocols_len;
    unsigned char *alpn_protocols;
    size_t alpn_protocols_len;
} CTX_DATA;

/* |ctx_data| itself is stack-allocated. */
static void ctx_data_free_data(CTX_DATA *ctx_data)
{
    OPENSSL_free(ctx_data->npn_protocols);
    ctx_data->npn_protocols = NULL;
    OPENSSL_free(ctx_data->alpn_protocols);
    ctx_data->alpn_protocols = NULL;
}

E
Emilia Kasper 已提交
65 66
static int ex_data_idx;

R
Richard Levitte 已提交
67
static void info_cb(const SSL *s, int where, int ret)
E
Emilia Kasper 已提交
68 69 70 71 72 73 74 75 76 77 78 79
{
    if (where & SSL_CB_ALERT) {
        HANDSHAKE_EX_DATA *ex_data =
            (HANDSHAKE_EX_DATA*)(SSL_get_ex_data(s, ex_data_idx));
        if (where & SSL_CB_WRITE) {
            ex_data->alert_sent = ret;
        } else {
            ex_data->alert_received = ret;
        }
    }
}

80
/* Select the appropriate server CTX.
81 82 83 84 85 86
 * Returns SSL_TLSEXT_ERR_OK if a match was found.
 * If |ignore| is 1, returns SSL_TLSEXT_ERR_NOACK on mismatch.
 * Otherwise, returns SSL_TLSEXT_ERR_ALERT_FATAL on mismatch.
 * An empty SNI extension also returns SSL_TSLEXT_ERR_NOACK.
 */
static int select_server_ctx(SSL *s, void *arg, int ignore)
E
Emilia Kasper 已提交
87 88
{
    const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
89 90 91 92 93 94 95 96 97
    HANDSHAKE_EX_DATA *ex_data =
        (HANDSHAKE_EX_DATA*)(SSL_get_ex_data(s, ex_data_idx));

    if (servername == NULL) {
        ex_data->servername = SSL_TEST_SERVERNAME_SERVER1;
        return SSL_TLSEXT_ERR_NOACK;
    }

    if (strcmp(servername, "server2") == 0) {
E
Emilia Kasper 已提交
98 99 100 101 102 103 104 105 106
        SSL_CTX *new_ctx = (SSL_CTX*)arg;
        SSL_set_SSL_CTX(s, new_ctx);
        /*
         * Copy over all the SSL_CTX options - reasonable behavior
         * allows testing of cases where the options between two
         * contexts differ/conflict
         */
        SSL_clear_options(s, 0xFFFFFFFFL);
        SSL_set_options(s, SSL_CTX_get_options(new_ctx));
107 108 109 110 111 112 113 114 115 116 117 118

        ex_data->servername = SSL_TEST_SERVERNAME_SERVER2;
        return SSL_TLSEXT_ERR_OK;
    } else if (strcmp(servername, "server1") == 0) {
        ex_data->servername = SSL_TEST_SERVERNAME_SERVER1;
        return SSL_TLSEXT_ERR_OK;
    } else if (ignore) {
        ex_data->servername = SSL_TEST_SERVERNAME_SERVER1;
        return SSL_TLSEXT_ERR_NOACK;
    } else {
        /* Don't set an explicit alert, to test library defaults. */
        return SSL_TLSEXT_ERR_ALERT_FATAL;
E
Emilia Kasper 已提交
119
    }
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
}

/*
 * (RFC 6066):
 *  If the server understood the ClientHello extension but
 *  does not recognize the server name, the server SHOULD take one of two
 *  actions: either abort the handshake by sending a fatal-level
 *  unrecognized_name(112) alert or continue the handshake.
 *
 * This behaviour is up to the application to configure; we test both
 * configurations to ensure the state machine propagates the result
 * correctly.
 */
static int servername_ignore_cb(SSL *s, int *ad, void *arg)
{
    return select_server_ctx(s, arg, 1);
}

static int servername_reject_cb(SSL *s, int *ad, void *arg)
{
    return select_server_ctx(s, arg, 0);
E
Emilia Kasper 已提交
141 142
}

R
Richard Levitte 已提交
143
static int verify_reject_cb(X509_STORE_CTX *ctx, void *arg) {
144 145 146 147
    X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION);
    return 0;
}

R
Richard Levitte 已提交
148
static int verify_accept_cb(X509_STORE_CTX *ctx, void *arg) {
149 150 151
    return 1;
}

152
static int broken_session_ticket_cb(SSL *s, unsigned char *key_name, unsigned char *iv,
R
Richard Levitte 已提交
153
                                    EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc)
T
Todd Short 已提交
154 155 156 157
{
    return 0;
}

158
static int do_not_call_session_ticket_cb(SSL *s, unsigned char *key_name,
R
Richard Levitte 已提交
159 160 161
                                         unsigned char *iv,
                                         EVP_CIPHER_CTX *ctx,
                                         HMAC_CTX *hctx, int enc)
T
Todd Short 已提交
162 163 164 165 166 167 168
{
    HANDSHAKE_EX_DATA *ex_data =
        (HANDSHAKE_EX_DATA*)(SSL_get_ex_data(s, ex_data_idx));
    ex_data->session_ticket_do_not_call = 1;
    return 0;
}

169 170 171 172 173 174 175 176
/* Parse the comma-separated list into TLS format. */
static void parse_protos(const char *protos, unsigned char **out, size_t *outlen)
{
    size_t len, i, prefix;

    len = strlen(protos);

    /* Should never have reuse. */
E
Emilia Kasper 已提交
177
    TEST_check(*out == NULL);
178 179 180

    /* Test values are small, so we omit length limit checks. */
    *out = OPENSSL_malloc(len + 1);
E
Emilia Kasper 已提交
181
    TEST_check(*out != NULL);
182 183 184 185 186 187 188 189 190 191 192 193
    *outlen = len + 1;

    /*
     * foo => '3', 'f', 'o', 'o'
     * foo,bar => '3', 'f', 'o', 'o', '3', 'b', 'a', 'r'
     */
    memcpy(*out + 1, protos, len);

    prefix = 0;
    i = prefix + 1;
    while (i <= len) {
        if ((*out)[i] == ',') {
E
Emilia Kasper 已提交
194
            TEST_check(i - 1 - prefix > 0);
195 196 197 198 199
            (*out)[prefix] = i - 1 - prefix;
            prefix = i;
        }
        i++;
    }
E
Emilia Kasper 已提交
200
    TEST_check(len - prefix > 0);
201 202 203
    (*out)[prefix] = len - prefix;
}

E
Emilia Kasper 已提交
204
#ifndef OPENSSL_NO_NEXTPROTONEG
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
/*
 * The client SHOULD select the first protocol advertised by the server that it
 * also supports.  In the event that the client doesn't support any of server's
 * protocols, or the server doesn't advertise any, it SHOULD select the first
 * protocol that it supports.
 */
static int client_npn_cb(SSL *s, unsigned char **out, unsigned char *outlen,
                         const unsigned char *in, unsigned int inlen,
                         void *arg)
{
    CTX_DATA *ctx_data = (CTX_DATA*)(arg);
    int ret;

    ret = SSL_select_next_proto(out, outlen, in, inlen,
                                ctx_data->npn_protocols,
                                ctx_data->npn_protocols_len);
    /* Accept both OPENSSL_NPN_NEGOTIATED and OPENSSL_NPN_NO_OVERLAP. */
E
Emilia Kasper 已提交
222
    TEST_check(ret == OPENSSL_NPN_NEGOTIATED || ret == OPENSSL_NPN_NO_OVERLAP);
223 224 225 226 227 228 229 230 231 232 233
    return SSL_TLSEXT_ERR_OK;
}

static int server_npn_cb(SSL *s, const unsigned char **data,
                         unsigned int *len, void *arg)
{
    CTX_DATA *ctx_data = (CTX_DATA*)(arg);
    *data = ctx_data->npn_protocols;
    *len = ctx_data->npn_protocols_len;
    return SSL_TLSEXT_ERR_OK;
}
E
Emilia Kasper 已提交
234
#endif
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266

/*
 * The server SHOULD select the most highly preferred protocol that it supports
 * and that is also advertised by the client.  In the event that the server
 * supports no protocols that the client advertises, then the server SHALL
 * respond with a fatal "no_application_protocol" alert.
 */
static int server_alpn_cb(SSL *s, const unsigned char **out,
                          unsigned char *outlen, const unsigned char *in,
                          unsigned int inlen, void *arg)
{
    CTX_DATA *ctx_data = (CTX_DATA*)(arg);
    int ret;

    /* SSL_select_next_proto isn't const-correct... */
    unsigned char *tmp_out;

    /*
     * The result points either to |in| or to |ctx_data->alpn_protocols|.
     * The callback is allowed to point to |in| or to a long-lived buffer,
     * so we can return directly without storing a copy.
     */
    ret = SSL_select_next_proto(&tmp_out, outlen,
                                ctx_data->alpn_protocols,
                                ctx_data->alpn_protocols_len, in, inlen);

    *out = tmp_out;
    /* Unlike NPN, we don't tolerate a mismatch. */
    return ret == OPENSSL_NPN_NEGOTIATED ? SSL_TLSEXT_ERR_OK
        : SSL_TLSEXT_ERR_NOACK;
}

267 268 269 270
/*
 * Configure callbacks and other properties that can't be set directly
 * in the server/client CONF.
 */
E
Emilia Kasper 已提交
271 272
static void configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
                                    SSL_CTX *client_ctx,
E
Emilia Kasper 已提交
273
                                    const SSL_TEST_EXTRA_CONF *extra,
274 275 276
                                    CTX_DATA *server_ctx_data,
                                    CTX_DATA *server2_ctx_data,
                                    CTX_DATA *client_ctx_data)
277
{
278 279 280
    unsigned char *ticket_keys;
    size_t ticket_key_len;

E
Emilia Kasper 已提交
281
    switch (extra->client.verify_callback) {
282
    case SSL_TEST_VERIFY_ACCEPT_ALL:
R
Richard Levitte 已提交
283
        SSL_CTX_set_cert_verify_callback(client_ctx, &verify_accept_cb,
284 285 286
                                         NULL);
        break;
    case SSL_TEST_VERIFY_REJECT_ALL:
R
Richard Levitte 已提交
287
        SSL_CTX_set_cert_verify_callback(client_ctx, &verify_reject_cb,
288 289 290 291 292
                                         NULL);
        break;
    default:
        break;
    }
E
Emilia Kasper 已提交
293 294

    /* link the two contexts for SNI purposes */
E
Emilia Kasper 已提交
295
    switch (extra->server.servername_callback) {
296 297 298 299 300 301 302 303 304 305 306 307
    case SSL_TEST_SERVERNAME_IGNORE_MISMATCH:
        SSL_CTX_set_tlsext_servername_callback(server_ctx, servername_ignore_cb);
        SSL_CTX_set_tlsext_servername_arg(server_ctx, server2_ctx);
        break;
    case SSL_TEST_SERVERNAME_REJECT_MISMATCH:
        SSL_CTX_set_tlsext_servername_callback(server_ctx, servername_reject_cb);
        SSL_CTX_set_tlsext_servername_arg(server_ctx, server2_ctx);
        break;
    default:
        break;
    }

E
Emilia Kasper 已提交
308 309 310 311 312
    /*
     * The initial_ctx/session_ctx always handles the encrypt/decrypt of the
     * session ticket. This ticket_key callback is assigned to the second
     * session (assigned via SNI), and should never be invoked
     */
313 314 315
    if (server2_ctx != NULL)
        SSL_CTX_set_tlsext_ticket_key_cb(server2_ctx,
                                         do_not_call_session_ticket_cb);
E
Emilia Kasper 已提交
316

E
Emilia Kasper 已提交
317
    if (extra->server.broken_session_ticket) {
R
Richard Levitte 已提交
318
        SSL_CTX_set_tlsext_ticket_key_cb(server_ctx, broken_session_ticket_cb);
T
Todd Short 已提交
319
    }
B
Ben Laurie 已提交
320
#ifndef OPENSSL_NO_NEXTPROTONEG
E
Emilia Kasper 已提交
321 322
    if (extra->server.npn_protocols != NULL) {
        parse_protos(extra->server.npn_protocols,
323 324 325 326 327
                     &server_ctx_data->npn_protocols,
                     &server_ctx_data->npn_protocols_len);
        SSL_CTX_set_next_protos_advertised_cb(server_ctx, server_npn_cb,
                                              server_ctx_data);
    }
E
Emilia Kasper 已提交
328 329
    if (extra->server2.npn_protocols != NULL) {
        parse_protos(extra->server2.npn_protocols,
330 331
                     &server2_ctx_data->npn_protocols,
                     &server2_ctx_data->npn_protocols_len);
E
Emilia Kasper 已提交
332
        TEST_check(server2_ctx != NULL);
333 334 335
        SSL_CTX_set_next_protos_advertised_cb(server2_ctx, server_npn_cb,
                                              server2_ctx_data);
    }
E
Emilia Kasper 已提交
336 337
    if (extra->client.npn_protocols != NULL) {
        parse_protos(extra->client.npn_protocols,
338 339 340 341 342
                     &client_ctx_data->npn_protocols,
                     &client_ctx_data->npn_protocols_len);
        SSL_CTX_set_next_proto_select_cb(client_ctx, client_npn_cb,
                                         client_ctx_data);
    }
E
Emilia Kasper 已提交
343
#endif
E
Emilia Kasper 已提交
344 345
    if (extra->server.alpn_protocols != NULL) {
        parse_protos(extra->server.alpn_protocols,
346 347 348 349
                     &server_ctx_data->alpn_protocols,
                     &server_ctx_data->alpn_protocols_len);
        SSL_CTX_set_alpn_select_cb(server_ctx, server_alpn_cb, server_ctx_data);
    }
E
Emilia Kasper 已提交
350
    if (extra->server2.alpn_protocols != NULL) {
E
Emilia Kasper 已提交
351
        TEST_check(server2_ctx != NULL);
E
Emilia Kasper 已提交
352
        parse_protos(extra->server2.alpn_protocols,
353 354 355 356
                     &server2_ctx_data->alpn_protocols,
                     &server2_ctx_data->alpn_protocols_len);
        SSL_CTX_set_alpn_select_cb(server2_ctx, server_alpn_cb, server2_ctx_data);
    }
E
Emilia Kasper 已提交
357
    if (extra->client.alpn_protocols != NULL) {
358 359
        unsigned char *alpn_protos = NULL;
        size_t alpn_protos_len;
E
Emilia Kasper 已提交
360
        parse_protos(extra->client.alpn_protocols,
361 362
                     &alpn_protos, &alpn_protos_len);
        /* Reversed return value convention... */
E
Emilia Kasper 已提交
363 364
        TEST_check(SSL_CTX_set_alpn_protos(client_ctx, alpn_protos,
                                           alpn_protos_len) == 0);
365 366
        OPENSSL_free(alpn_protos);
    }
E
Emilia Kasper 已提交
367

368 369 370 371 372 373
    /*
     * Use fixed session ticket keys so that we can decrypt a ticket created with
     * one CTX in another CTX. Don't address server2 for the moment.
     */
    ticket_key_len = SSL_CTX_set_tlsext_ticket_keys(server_ctx, NULL, 0);
    ticket_keys = OPENSSL_zalloc(ticket_key_len);
E
Emilia Kasper 已提交
374 375 376
    TEST_check(ticket_keys != NULL);
    TEST_check(SSL_CTX_set_tlsext_ticket_keys(server_ctx, ticket_keys,
                                              ticket_key_len) == 1);
377
    OPENSSL_free(ticket_keys);
378

379 380
    /* The default log list includes EC keys, so CT can't work without EC. */
#if !defined(OPENSSL_NO_CT) && !defined(OPENSSL_NO_EC)
E
Emilia Kasper 已提交
381
    TEST_check(SSL_CTX_set_default_ctlog_list_file(client_ctx));
382 383
    switch (extra->client.ct_validation) {
    case SSL_TEST_CT_VALIDATION_PERMISSIVE:
E
Emilia Kasper 已提交
384
        TEST_check(SSL_CTX_enable_ct(client_ctx, SSL_CT_VALIDATION_PERMISSIVE));
385 386
        break;
    case SSL_TEST_CT_VALIDATION_STRICT:
E
Emilia Kasper 已提交
387
        TEST_check(SSL_CTX_enable_ct(client_ctx, SSL_CT_VALIDATION_STRICT));
388 389 390 391 392
        break;
    case SSL_TEST_CT_VALIDATION_NONE:
        break;
    }
#endif
T
Todd Short 已提交
393 394
}

395
/* Configure per-SSL callbacks and other properties. */
T
Todd Short 已提交
396
static void configure_handshake_ssl(SSL *server, SSL *client,
E
Emilia Kasper 已提交
397
                                    const SSL_TEST_EXTRA_CONF *extra)
T
Todd Short 已提交
398
{
E
Emilia Kasper 已提交
399
    if (extra->client.servername != SSL_TEST_SERVERNAME_NONE)
E
Emilia Kasper 已提交
400
        SSL_set_tlsext_host_name(client,
E
Emilia Kasper 已提交
401
                                 ssl_servername_name(extra->client.servername));
402 403 404
}


E
Emilia Kasper 已提交
405 406 407 408 409 410
typedef enum {
    PEER_SUCCESS,
    PEER_RETRY,
    PEER_ERROR
} peer_status_t;

411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
/*
 * RFC 5246 says:
 *
 * Note that as of TLS 1.1,
 *     failure to properly close a connection no longer requires that a
 *     session not be resumed.  This is a change from TLS 1.0 to conform
 *     with widespread implementation practice.
 *
 * However,
 * (a) OpenSSL requires that a connection be shutdown for all protocol versions.
 * (b) We test lower versions, too.
 * So we just implement shutdown. We do a full bidirectional shutdown so that we
 * can compare sent and received close_notify alerts and get some test coverage
 * for SSL_shutdown as a bonus.
 */
static peer_status_t do_handshake_step(SSL *ssl, int shutdown)
E
Emilia Kasper 已提交
427 428 429
{
    int ret;

430
    ret = shutdown ? SSL_shutdown(ssl) : SSL_do_handshake(ssl);
E
Emilia Kasper 已提交
431 432 433 434

    if (ret == 1) {
        return PEER_SUCCESS;
    } else if (ret == 0) {
435
        return shutdown ? PEER_RETRY : PEER_ERROR;
E
Emilia Kasper 已提交
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
    } else {
        int error = SSL_get_error(ssl, ret);
        /* Memory bios should never block with SSL_ERROR_WANT_WRITE. */
        if (error == SSL_ERROR_WANT_READ)
            return PEER_RETRY;
        else
            return PEER_ERROR;
    }
}

typedef enum {
    /* Both parties succeeded. */
    HANDSHAKE_SUCCESS,
    /* Client errored. */
    CLIENT_ERROR,
    /* Server errored. */
    SERVER_ERROR,
    /* Peers are in inconsistent state. */
    INTERNAL_ERROR,
    /* One or both peers not done. */
    HANDSHAKE_RETRY
} handshake_status_t;

/*
 * Determine the handshake outcome.
 * last_status: the status of the peer to have acted last.
 * previous_status: the status of the peer that didn't act last.
 * client_spoke_last: 1 if the client went last.
 */
static handshake_status_t handshake_status(peer_status_t last_status,
                                           peer_status_t previous_status,
                                           int client_spoke_last)
{
    switch (last_status) {
    case PEER_SUCCESS:
        switch (previous_status) {
        case PEER_SUCCESS:
            /* Both succeeded. */
            return HANDSHAKE_SUCCESS;
        case PEER_RETRY:
            /* Let the first peer finish. */
            return HANDSHAKE_RETRY;
        case PEER_ERROR:
            /*
             * Second peer succeeded despite the fact that the first peer
             * already errored. This shouldn't happen.
             */
            return INTERNAL_ERROR;
        }

    case PEER_RETRY:
        if (previous_status == PEER_RETRY) {
            /* Neither peer is done. */
            return HANDSHAKE_RETRY;
        } else {
            /*
             * Deadlock: second peer is waiting for more input while first
             * peer thinks they're done (no more input is coming).
             */
            return INTERNAL_ERROR;
        }
    case PEER_ERROR:
        switch (previous_status) {
        case PEER_SUCCESS:
            /*
             * First peer succeeded but second peer errored.
             * TODO(emilia): we should be able to continue here (with some
             * application data?) to ensure the first peer receives the
             * alert / close_notify.
             */
            return client_spoke_last ? CLIENT_ERROR : SERVER_ERROR;
        case PEER_RETRY:
            /* We errored; let the peer finish. */
            return HANDSHAKE_RETRY;
        case PEER_ERROR:
            /* Both peers errored. Return the one that errored first. */
            return client_spoke_last ? SERVER_ERROR : CLIENT_ERROR;
        }
    }
    /* Control should never reach here. */
    return INTERNAL_ERROR;
}

519 520 521 522 523 524 525 526 527
/* Convert unsigned char buf's that shouldn't contain any NUL-bytes to char. */
static char *dup_str(const unsigned char *in, size_t len)
{
    char *ret;

    if(len == 0)
        return NULL;

    /* Assert that the string does not contain NUL-bytes. */
E
Emilia Kasper 已提交
528
    TEST_check(OPENSSL_strnlen((const char*)(in), len) == len);
529
    ret = OPENSSL_strndup((const char*)(in), len);
E
Emilia Kasper 已提交
530
    TEST_check(ret != NULL);
531 532 533
    return ret;
}

534 535
static HANDSHAKE_RESULT *do_handshake_internal(
    SSL_CTX *server_ctx, SSL_CTX *server2_ctx, SSL_CTX *client_ctx,
E
Emilia Kasper 已提交
536
    const SSL_TEST_EXTRA_CONF *extra, SSL_SESSION *session_in,
537
    SSL_SESSION **session_out)
E
Emilia Kasper 已提交
538 539 540 541
{
    SSL *server, *client;
    BIO *client_to_server, *server_to_client;
    HANDSHAKE_EX_DATA server_ex_data, client_ex_data;
542 543
    CTX_DATA client_ctx_data, server_ctx_data, server2_ctx_data;
    HANDSHAKE_RESULT *ret = HANDSHAKE_RESULT_new();
544
    int client_turn = 1, shutdown = 0;
E
Emilia Kasper 已提交
545 546
    peer_status_t client_status = PEER_RETRY, server_status = PEER_RETRY;
    handshake_status_t status = HANDSHAKE_RETRY;
T
Todd Short 已提交
547
    unsigned char* tick = NULL;
548
    size_t tick_len = 0;
T
Todd Short 已提交
549
    SSL_SESSION* sess = NULL;
550 551 552
    const unsigned char *proto = NULL;
    /* API dictates unsigned int rather than size_t. */
    unsigned int proto_len = 0;
E
Emilia Kasper 已提交
553

554 555 556 557
    memset(&server_ctx_data, 0, sizeof(server_ctx_data));
    memset(&server2_ctx_data, 0, sizeof(server2_ctx_data));
    memset(&client_ctx_data, 0, sizeof(client_ctx_data));

E
Emilia Kasper 已提交
558
    configure_handshake_ctx(server_ctx, server2_ctx, client_ctx, extra,
559
                            &server_ctx_data, &server2_ctx_data, &client_ctx_data);
560

E
Emilia Kasper 已提交
561 562
    server = SSL_new(server_ctx);
    client = SSL_new(client_ctx);
E
Emilia Kasper 已提交
563 564
    TEST_check(server != NULL);
    TEST_check(client != NULL);
E
Emilia Kasper 已提交
565

E
Emilia Kasper 已提交
566
    configure_handshake_ssl(server, client, extra);
567 568
    if (session_in != NULL) {
        /* In case we're testing resumption without tickets. */
E
Emilia Kasper 已提交
569 570
        TEST_check(SSL_CTX_add_session(server_ctx, session_in));
        TEST_check(SSL_set_session(client, session_in));
571
    }
T
Todd Short 已提交
572

E
Emilia Kasper 已提交
573 574
    memset(&server_ex_data, 0, sizeof(server_ex_data));
    memset(&client_ex_data, 0, sizeof(client_ex_data));
575 576

    ret->result = SSL_TEST_INTERNAL_ERROR;
E
Emilia Kasper 已提交
577 578 579 580

    client_to_server = BIO_new(BIO_s_mem());
    server_to_client = BIO_new(BIO_s_mem());

E
Emilia Kasper 已提交
581
    TEST_check(client_to_server != NULL && server_to_client != NULL);
E
Emilia Kasper 已提交
582 583 584 585 586 587 588 589 590 591

    /* Non-blocking bio. */
    BIO_set_nbio(client_to_server, 1);
    BIO_set_nbio(server_to_client, 1);

    SSL_set_connect_state(client);
    SSL_set_accept_state(server);

    /* The bios are now owned by the SSL object. */
    SSL_set_bio(client, server_to_client, client_to_server);
E
Emilia Kasper 已提交
592 593
    TEST_check(BIO_up_ref(server_to_client) > 0);
    TEST_check(BIO_up_ref(client_to_server) > 0);
E
Emilia Kasper 已提交
594 595 596
    SSL_set_bio(server, client_to_server, server_to_client);

    ex_data_idx = SSL_get_ex_new_index(0, "ex data", NULL, NULL, NULL);
E
Emilia Kasper 已提交
597
    TEST_check(ex_data_idx >= 0);
E
Emilia Kasper 已提交
598

E
Emilia Kasper 已提交
599
    TEST_check(SSL_set_ex_data(server, ex_data_idx,
E
Emilia Kasper 已提交
600
                                   &server_ex_data) == 1);
E
Emilia Kasper 已提交
601
    TEST_check(SSL_set_ex_data(client, ex_data_idx,
E
Emilia Kasper 已提交
602 603
                                   &client_ex_data) == 1);

R
Richard Levitte 已提交
604 605
    SSL_set_info_callback(server, &info_cb);
    SSL_set_info_callback(client, &info_cb);
E
Emilia Kasper 已提交
606 607 608 609 610 611 612 613 614 615 616

    /*
     * Half-duplex handshake loop.
     * Client and server speak to each other synchronously in the same process.
     * We use non-blocking BIOs, so whenever one peer blocks for read, it
     * returns PEER_RETRY to indicate that it's the other peer's turn to write.
     * The handshake succeeds once both peers have succeeded. If one peer
     * errors out, we also let the other peer retry (and presumably fail).
     */
    for(;;) {
        if (client_turn) {
617
            client_status = do_handshake_step(client, shutdown);
E
Emilia Kasper 已提交
618 619 620
            status = handshake_status(client_status, server_status,
                                      1 /* client went last */);
        } else {
621
            server_status = do_handshake_step(server, shutdown);
E
Emilia Kasper 已提交
622 623 624 625 626 627
            status = handshake_status(server_status, client_status,
                                      0 /* server went last */);
        }

        switch (status) {
        case HANDSHAKE_SUCCESS:
628 629 630 631 632 633 634 635 636
            if (shutdown) {
                ret->result = SSL_TEST_SUCCESS;
                goto err;
            } else {
                client_status = server_status = PEER_RETRY;
                shutdown = 1;
                client_turn = 1;
                break;
            }
E
Emilia Kasper 已提交
637
        case CLIENT_ERROR:
638
            ret->result = SSL_TEST_CLIENT_FAIL;
E
Emilia Kasper 已提交
639 640
            goto err;
        case SERVER_ERROR:
641
            ret->result = SSL_TEST_SERVER_FAIL;
E
Emilia Kasper 已提交
642 643
            goto err;
        case INTERNAL_ERROR:
644
            ret->result = SSL_TEST_INTERNAL_ERROR;
E
Emilia Kasper 已提交
645 646 647 648 649 650 651 652
            goto err;
        case HANDSHAKE_RETRY:
            /* Continue. */
            client_turn ^= 1;
            break;
        }
    }
 err:
653 654 655 656 657 658 659
    ret->server_alert_sent = server_ex_data.alert_sent;
    ret->server_alert_received = client_ex_data.alert_received;
    ret->client_alert_sent = client_ex_data.alert_sent;
    ret->client_alert_received = server_ex_data.alert_received;
    ret->server_protocol = SSL_version(server);
    ret->client_protocol = SSL_version(client);
    ret->servername = server_ex_data.servername;
T
Todd Short 已提交
660
    if ((sess = SSL_get0_session(client)) != NULL)
661 662 663
        SSL_SESSION_get0_ticket(sess, &tick, &tick_len);
    if (tick == NULL || tick_len == 0)
        ret->session_ticket = SSL_TEST_SESSION_TICKET_NO;
T
Todd Short 已提交
664
    else
665 666 667
        ret->session_ticket = SSL_TEST_SESSION_TICKET_YES;
    ret->session_ticket_do_not_call = server_ex_data.session_ticket_do_not_call;

B
Ben Laurie 已提交
668
#ifndef OPENSSL_NO_NEXTPROTONEG
669 670 671 672 673
    SSL_get0_next_proto_negotiated(client, &proto, &proto_len);
    ret->client_npn_negotiated = dup_str(proto, proto_len);

    SSL_get0_next_proto_negotiated(server, &proto, &proto_len);
    ret->server_npn_negotiated = dup_str(proto, proto_len);
E
Emilia Kasper 已提交
674
#endif
675 676 677 678 679 680

    SSL_get0_alpn_selected(client, &proto, &proto_len);
    ret->client_alpn_negotiated = dup_str(proto, proto_len);

    SSL_get0_alpn_selected(server, &proto, &proto_len);
    ret->server_alpn_negotiated = dup_str(proto, proto_len);
E
Emilia Kasper 已提交
681

682 683 684 685 686 687
    ret->client_resumed = SSL_session_reused(client);
    ret->server_resumed = SSL_session_reused(server);

    if (session_out != NULL)
        *session_out = SSL_get1_session(client);

688 689 690
    ctx_data_free_data(&server_ctx_data);
    ctx_data_free_data(&server2_ctx_data);
    ctx_data_free_data(&client_ctx_data);
691

E
Emilia Kasper 已提交
692 693 694 695
    SSL_free(server);
    SSL_free(client);
    return ret;
}
696 697 698

HANDSHAKE_RESULT *do_handshake(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
                               SSL_CTX *client_ctx, SSL_CTX *resume_server_ctx,
E
Emilia Kasper 已提交
699
                               SSL_CTX *resume_client_ctx,
700 701 702 703 704 705
                               const SSL_TEST_CTX *test_ctx)
{
    HANDSHAKE_RESULT *result;
    SSL_SESSION *session = NULL;

    result = do_handshake_internal(server_ctx, server2_ctx, client_ctx,
E
Emilia Kasper 已提交
706
                                   &test_ctx->extra, NULL, &session);
707 708 709
    if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_SIMPLE)
        goto end;

E
Emilia Kasper 已提交
710
    TEST_check(test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RESUME);
711 712 713 714 715 716 717 718

    if (result->result != SSL_TEST_SUCCESS) {
        result->result = SSL_TEST_FIRST_HANDSHAKE_FAILED;
        return result;
    }

    HANDSHAKE_RESULT_free(result);
    /* We don't support SNI on second handshake yet, so server2_ctx is NULL. */
E
Emilia Kasper 已提交
719
    result = do_handshake_internal(resume_server_ctx, NULL, resume_client_ctx,
E
Emilia Kasper 已提交
720
                                   &test_ctx->resume_extra, session, NULL);
721 722 723 724
 end:
    SSL_SESSION_free(session);
    return result;
}