Blame test/ssltest_old.c

Packit c4476c
/*
Packit c4476c
 * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
Packit c4476c
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
Packit c4476c
 * Copyright 2005 Nokia. All rights reserved.
Packit c4476c
 *
Packit c4476c
 * Licensed under the OpenSSL license (the "License").  You may not use
Packit c4476c
 * this file except in compliance with the License.  You can obtain a copy
Packit c4476c
 * in the file LICENSE in the source distribution or at
Packit c4476c
 * https://www.openssl.org/source/license.html
Packit c4476c
 */
Packit c4476c
Packit c4476c
#include "e_os.h"
Packit c4476c
Packit c4476c
/* Or gethostname won't be declared properly on Linux and GNU platforms. */
Packit c4476c
#ifndef _BSD_SOURCE
Packit c4476c
# define _BSD_SOURCE 1
Packit c4476c
#endif
Packit c4476c
#ifndef _DEFAULT_SOURCE
Packit c4476c
# define _DEFAULT_SOURCE 1
Packit c4476c
#endif
Packit c4476c
Packit c4476c
#include <assert.h>
Packit c4476c
#include <errno.h>
Packit c4476c
#include <limits.h>
Packit c4476c
#include <stdio.h>
Packit c4476c
#include <stdlib.h>
Packit c4476c
#include <string.h>
Packit c4476c
#include <time.h>
Packit c4476c
Packit c4476c
#include "internal/nelem.h"
Packit c4476c
Packit c4476c
#ifdef OPENSSL_SYS_VMS
Packit c4476c
/*
Packit c4476c
 * Or isascii won't be declared properly on VMS (at least with DECompHP C).
Packit c4476c
 */
Packit c4476c
# define _XOPEN_SOURCE 500
Packit c4476c
#endif
Packit c4476c
Packit c4476c
#include <ctype.h>
Packit c4476c
Packit c4476c
#include <openssl/bio.h>
Packit c4476c
#include <openssl/crypto.h>
Packit c4476c
#include <openssl/evp.h>
Packit c4476c
#include <openssl/x509.h>
Packit c4476c
#include <openssl/x509v3.h>
Packit c4476c
#include <openssl/ssl.h>
Packit c4476c
#include <openssl/err.h>
Packit c4476c
#include <openssl/rand.h>
Packit c4476c
#ifndef OPENSSL_NO_RSA
Packit c4476c
# include <openssl/rsa.h>
Packit c4476c
#endif
Packit c4476c
#ifndef OPENSSL_NO_DSA
Packit c4476c
# include <openssl/dsa.h>
Packit c4476c
#endif
Packit c4476c
#ifndef OPENSSL_NO_DH
Packit c4476c
# include <openssl/dh.h>
Packit c4476c
#endif
Packit c4476c
#include <openssl/bn.h>
Packit c4476c
#ifndef OPENSSL_NO_CT
Packit c4476c
# include <openssl/ct.h>
Packit c4476c
#endif
Packit c4476c
Packit c4476c
/*
Packit c4476c
 * Or gethostname won't be declared properly
Packit c4476c
 * on Compaq platforms (at least with DEC C).
Packit c4476c
 * Do not try to put it earlier, or IPv6 includes
Packit c4476c
 * get screwed...
Packit c4476c
 */
Packit c4476c
#define _XOPEN_SOURCE_EXTENDED  1
Packit c4476c
Packit c4476c
#ifdef OPENSSL_SYS_WINDOWS
Packit c4476c
# include <winsock.h>
Packit c4476c
#else
Packit c4476c
# include OPENSSL_UNISTD
Packit c4476c
#endif
Packit c4476c
Packit c4476c
static SSL_CTX *s_ctx = NULL;
Packit c4476c
static SSL_CTX *s_ctx2 = NULL;
Packit c4476c
Packit c4476c
/*
Packit c4476c
 * There is really no standard for this, so let's assign something
Packit c4476c
 * only for this test
Packit c4476c
 */
Packit c4476c
#define COMP_ZLIB       1
Packit c4476c
Packit c4476c
static int verify_callback(int ok, X509_STORE_CTX *ctx);
Packit c4476c
static int app_verify_callback(X509_STORE_CTX *ctx, void *arg);
Packit c4476c
#define APP_CALLBACK_STRING "Test Callback Argument"
Packit c4476c
struct app_verify_arg {
Packit c4476c
    char *string;
Packit c4476c
    int app_verify;
Packit c4476c
};
Packit c4476c
Packit c4476c
#ifndef OPENSSL_NO_DH
Packit c4476c
static DH *get_dh512(void);
Packit c4476c
static DH *get_dh1024(void);
Packit c4476c
static DH *get_dh1024dsa(void);
Packit c4476c
#endif
Packit c4476c
Packit c4476c
static char *psk_key = NULL;    /* by default PSK is not used */
Packit c4476c
#ifndef OPENSSL_NO_PSK
Packit c4476c
static unsigned int psk_client_callback(SSL *ssl, const char *hint,
Packit c4476c
                                        char *identity,
Packit c4476c
                                        unsigned int max_identity_len,
Packit c4476c
                                        unsigned char *psk,
Packit c4476c
                                        unsigned int max_psk_len);
Packit c4476c
static unsigned int psk_server_callback(SSL *ssl, const char *identity,
Packit c4476c
                                        unsigned char *psk,
Packit c4476c
                                        unsigned int max_psk_len);
Packit c4476c
#endif
Packit c4476c
Packit c4476c
static BIO *bio_err = NULL;
Packit c4476c
static BIO *bio_stdout = NULL;
Packit c4476c
Packit c4476c
#ifndef OPENSSL_NO_NEXTPROTONEG
Packit c4476c
/* Note that this code assumes that this is only a one element list: */
Packit c4476c
static const char NEXT_PROTO_STRING[] = "\x09testproto";
Packit c4476c
static int npn_client = 0;
Packit c4476c
static int npn_server = 0;
Packit c4476c
static int npn_server_reject = 0;
Packit c4476c
Packit c4476c
static int cb_client_npn(SSL *s, unsigned char **out, unsigned char *outlen,
Packit c4476c
                         const unsigned char *in, unsigned int inlen,
Packit c4476c
                         void *arg)
Packit c4476c
{
Packit c4476c
    /*
Packit c4476c
     * This callback only returns the protocol string, rather than a length
Packit c4476c
     * prefixed set. We assume that NEXT_PROTO_STRING is a one element list
Packit c4476c
     * and remove the first byte to chop off the length prefix.
Packit c4476c
     */
Packit c4476c
    *out = (unsigned char *)NEXT_PROTO_STRING + 1;
Packit c4476c
    *outlen = sizeof(NEXT_PROTO_STRING) - 2;
Packit c4476c
    return SSL_TLSEXT_ERR_OK;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int cb_server_npn(SSL *s, const unsigned char **data,
Packit c4476c
                         unsigned int *len, void *arg)
Packit c4476c
{
Packit c4476c
    *data = (const unsigned char *)NEXT_PROTO_STRING;
Packit c4476c
    *len = sizeof(NEXT_PROTO_STRING) - 1;
Packit c4476c
    return SSL_TLSEXT_ERR_OK;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int cb_server_rejects_npn(SSL *s, const unsigned char **data,
Packit c4476c
                                 unsigned int *len, void *arg)
Packit c4476c
{
Packit c4476c
    return SSL_TLSEXT_ERR_NOACK;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int verify_npn(SSL *client, SSL *server)
Packit c4476c
{
Packit c4476c
    const unsigned char *client_s;
Packit c4476c
    unsigned client_len;
Packit c4476c
    const unsigned char *server_s;
Packit c4476c
    unsigned server_len;
Packit c4476c
Packit c4476c
    SSL_get0_next_proto_negotiated(client, &client_s, &client_len);
Packit c4476c
    SSL_get0_next_proto_negotiated(server, &server_s, &server_len);
Packit c4476c
Packit c4476c
    if (client_len) {
Packit c4476c
        BIO_printf(bio_stdout, "Client NPN: ");
Packit c4476c
        BIO_write(bio_stdout, client_s, client_len);
Packit c4476c
        BIO_printf(bio_stdout, "\n");
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (server_len) {
Packit c4476c
        BIO_printf(bio_stdout, "Server NPN: ");
Packit c4476c
        BIO_write(bio_stdout, server_s, server_len);
Packit c4476c
        BIO_printf(bio_stdout, "\n");
Packit c4476c
    }
Packit c4476c
Packit c4476c
    /*
Packit c4476c
     * If an NPN string was returned, it must be the protocol that we
Packit c4476c
     * expected to negotiate.
Packit c4476c
     */
Packit c4476c
    if (client_len && (client_len != sizeof(NEXT_PROTO_STRING) - 2 ||
Packit c4476c
                       memcmp(client_s, NEXT_PROTO_STRING + 1, client_len)))
Packit c4476c
        return -1;
Packit c4476c
    if (server_len && (server_len != sizeof(NEXT_PROTO_STRING) - 2 ||
Packit c4476c
                       memcmp(server_s, NEXT_PROTO_STRING + 1, server_len)))
Packit c4476c
        return -1;
Packit c4476c
Packit c4476c
    if (!npn_client && client_len)
Packit c4476c
        return -1;
Packit c4476c
    if (!npn_server && server_len)
Packit c4476c
        return -1;
Packit c4476c
    if (npn_server_reject && server_len)
Packit c4476c
        return -1;
Packit c4476c
    if (npn_client && npn_server && (!client_len || !server_len))
Packit c4476c
        return -1;
Packit c4476c
Packit c4476c
    return 0;
Packit c4476c
}
Packit c4476c
#endif
Packit c4476c
Packit c4476c
static const char *alpn_client;
Packit c4476c
static char *alpn_server;
Packit c4476c
static char *alpn_server2;
Packit c4476c
static const char *alpn_expected;
Packit c4476c
static unsigned char *alpn_selected;
Packit c4476c
static const char *server_min_proto;
Packit c4476c
static const char *server_max_proto;
Packit c4476c
static const char *client_min_proto;
Packit c4476c
static const char *client_max_proto;
Packit c4476c
static const char *should_negotiate;
Packit c4476c
static const char *sn_client;
Packit c4476c
static const char *sn_server1;
Packit c4476c
static const char *sn_server2;
Packit c4476c
static int sn_expect = 0;
Packit c4476c
static const char *server_sess_out;
Packit c4476c
static const char *server_sess_in;
Packit c4476c
static const char *client_sess_out;
Packit c4476c
static const char *client_sess_in;
Packit c4476c
static SSL_SESSION *server_sess;
Packit c4476c
static SSL_SESSION *client_sess;
Packit c4476c
Packit c4476c
static int servername_cb(SSL *s, int *ad, void *arg)
Packit c4476c
{
Packit c4476c
    const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
Packit c4476c
    if (sn_server2 == NULL) {
Packit c4476c
        BIO_printf(bio_stdout, "Servername 2 is NULL\n");
Packit c4476c
        return SSL_TLSEXT_ERR_NOACK;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (servername) {
Packit c4476c
        if (s_ctx2 != NULL && sn_server2 != NULL &&
Packit c4476c
            !strcasecmp(servername, sn_server2)) {
Packit c4476c
            BIO_printf(bio_stdout, "Switching server context.\n");
Packit c4476c
            SSL_set_SSL_CTX(s, s_ctx2);
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
    return SSL_TLSEXT_ERR_OK;
Packit c4476c
}
Packit c4476c
static int verify_servername(SSL *client, SSL *server)
Packit c4476c
{
Packit c4476c
    /* just need to see if sn_context is what we expect */
Packit c4476c
    SSL_CTX* ctx = SSL_get_SSL_CTX(server);
Packit c4476c
    if (sn_expect == 0)
Packit c4476c
        return 0;
Packit c4476c
    if (sn_expect == 1 && ctx == s_ctx)
Packit c4476c
        return 0;
Packit c4476c
    if (sn_expect == 2 && ctx == s_ctx2)
Packit c4476c
        return 0;
Packit c4476c
    BIO_printf(bio_stdout, "Servername: expected context %d\n", sn_expect);
Packit c4476c
    if (ctx == s_ctx2)
Packit c4476c
        BIO_printf(bio_stdout, "Servername: context is 2\n");
Packit c4476c
    else if (ctx == s_ctx)
Packit c4476c
        BIO_printf(bio_stdout, "Servername: context is 1\n");
Packit c4476c
    else
Packit c4476c
        BIO_printf(bio_stdout, "Servername: context is unknown\n");
Packit c4476c
    return -1;
Packit c4476c
}
Packit c4476c
Packit c4476c
Packit c4476c
/*-
Packit c4476c
 * next_protos_parse parses a comma separated list of strings into a string
Packit c4476c
 * in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
Packit c4476c
 *   outlen: (output) set to the length of the resulting buffer on success.
Packit c4476c
 *   in: a NUL terminated string like "abc,def,ghi"
Packit c4476c
 *
Packit c4476c
 *   returns: a malloced buffer or NULL on failure.
Packit c4476c
 */
Packit c4476c
static unsigned char *next_protos_parse(size_t *outlen,
Packit c4476c
                                        const char *in)
Packit c4476c
{
Packit c4476c
    size_t len;
Packit c4476c
    unsigned char *out;
Packit c4476c
    size_t i, start = 0;
Packit c4476c
Packit c4476c
    len = strlen(in);
Packit c4476c
    if (len >= 65535)
Packit c4476c
        return NULL;
Packit c4476c
Packit c4476c
    out = OPENSSL_malloc(strlen(in) + 1);
Packit c4476c
    if (!out)
Packit c4476c
        return NULL;
Packit c4476c
Packit c4476c
    for (i = 0; i <= len; ++i) {
Packit c4476c
        if (i == len || in[i] == ',') {
Packit c4476c
            if (i - start > 255) {
Packit c4476c
                OPENSSL_free(out);
Packit c4476c
                return NULL;
Packit c4476c
            }
Packit c4476c
            out[start] = (unsigned char)(i - start);
Packit c4476c
            start = i + 1;
Packit c4476c
        } else
Packit c4476c
            out[i + 1] = in[i];
Packit c4476c
    }
Packit c4476c
Packit c4476c
    *outlen = len + 1;
Packit c4476c
    return out;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int cb_server_alpn(SSL *s, const unsigned char **out,
Packit c4476c
                          unsigned char *outlen, const unsigned char *in,
Packit c4476c
                          unsigned int inlen, void *arg)
Packit c4476c
{
Packit c4476c
    unsigned char *protos;
Packit c4476c
    size_t protos_len;
Packit c4476c
    char* alpn_str = arg;
Packit c4476c
Packit c4476c
    protos = next_protos_parse(&protos_len, alpn_str);
Packit c4476c
    if (protos == NULL) {
Packit c4476c
        fprintf(stderr, "failed to parser ALPN server protocol string: %s\n",
Packit c4476c
                alpn_str);
Packit c4476c
        abort();
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (SSL_select_next_proto
Packit c4476c
        ((unsigned char **)out, outlen, protos, protos_len, in,
Packit c4476c
         inlen) != OPENSSL_NPN_NEGOTIATED) {
Packit c4476c
        OPENSSL_free(protos);
Packit c4476c
        return SSL_TLSEXT_ERR_NOACK;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    /*
Packit c4476c
     * Make a copy of the selected protocol which will be freed in
Packit c4476c
     * verify_alpn.
Packit c4476c
     */
Packit c4476c
    alpn_selected = OPENSSL_malloc(*outlen);
Packit c4476c
    memcpy(alpn_selected, *out, *outlen);
Packit c4476c
    *out = alpn_selected;
Packit c4476c
Packit c4476c
    OPENSSL_free(protos);
Packit c4476c
    return SSL_TLSEXT_ERR_OK;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int verify_alpn(SSL *client, SSL *server)
Packit c4476c
{
Packit c4476c
    const unsigned char *client_proto, *server_proto;
Packit c4476c
    unsigned int client_proto_len = 0, server_proto_len = 0;
Packit c4476c
    SSL_get0_alpn_selected(client, &client_proto, &client_proto_len);
Packit c4476c
    SSL_get0_alpn_selected(server, &server_proto, &server_proto_len);
Packit c4476c
Packit c4476c
    OPENSSL_free(alpn_selected);
Packit c4476c
    alpn_selected = NULL;
Packit c4476c
Packit c4476c
    if (client_proto_len != server_proto_len) {
Packit c4476c
        BIO_printf(bio_stdout, "ALPN selected protocols differ!\n");
Packit c4476c
        goto err;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (client_proto != NULL &&
Packit c4476c
        memcmp(client_proto, server_proto, client_proto_len) != 0) {
Packit c4476c
        BIO_printf(bio_stdout, "ALPN selected protocols differ!\n");
Packit c4476c
        goto err;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (client_proto_len > 0 && alpn_expected == NULL) {
Packit c4476c
        BIO_printf(bio_stdout, "ALPN unexpectedly negotiated\n");
Packit c4476c
        goto err;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (alpn_expected != NULL &&
Packit c4476c
        (client_proto_len != strlen(alpn_expected) ||
Packit c4476c
         memcmp(client_proto, alpn_expected, client_proto_len) != 0)) {
Packit c4476c
        BIO_printf(bio_stdout,
Packit c4476c
                   "ALPN selected protocols not equal to expected protocol: %s\n",
Packit c4476c
                   alpn_expected);
Packit c4476c
        goto err;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    return 0;
Packit c4476c
Packit c4476c
 err:
Packit c4476c
    BIO_printf(bio_stdout, "ALPN results: client: '");
Packit c4476c
    BIO_write(bio_stdout, client_proto, client_proto_len);
Packit c4476c
    BIO_printf(bio_stdout, "', server: '");
Packit c4476c
    BIO_write(bio_stdout, server_proto, server_proto_len);
Packit c4476c
    BIO_printf(bio_stdout, "'\n");
Packit c4476c
    BIO_printf(bio_stdout, "ALPN configured: client: '%s', server: '",
Packit c4476c
                   alpn_client);
Packit c4476c
    if (SSL_get_SSL_CTX(server) == s_ctx2) {
Packit c4476c
        BIO_printf(bio_stdout, "%s'\n",
Packit c4476c
                   alpn_server2);
Packit c4476c
    } else {
Packit c4476c
        BIO_printf(bio_stdout, "%s'\n",
Packit c4476c
                   alpn_server);
Packit c4476c
    }
Packit c4476c
    return -1;
Packit c4476c
}
Packit c4476c
Packit c4476c
/*
Packit c4476c
 * WARNING : below extension types are *NOT* IETF assigned, and could
Packit c4476c
 * conflict if these types are reassigned and handled specially by OpenSSL
Packit c4476c
 * in the future
Packit c4476c
 */
Packit c4476c
#define TACK_EXT_TYPE 62208
Packit c4476c
#define CUSTOM_EXT_TYPE_0 1000
Packit c4476c
#define CUSTOM_EXT_TYPE_1 1001
Packit c4476c
#define CUSTOM_EXT_TYPE_2 1002
Packit c4476c
#define CUSTOM_EXT_TYPE_3 1003
Packit c4476c
Packit c4476c
static const char custom_ext_cli_string[] = "abc";
Packit c4476c
static const char custom_ext_srv_string[] = "defg";
Packit c4476c
Packit c4476c
/* These set from cmdline */
Packit c4476c
static char *serverinfo_file = NULL;
Packit c4476c
static int serverinfo_sct = 0;
Packit c4476c
static int serverinfo_tack = 0;
Packit c4476c
Packit c4476c
/* These set based on extension callbacks */
Packit c4476c
static int serverinfo_sct_seen = 0;
Packit c4476c
static int serverinfo_tack_seen = 0;
Packit c4476c
static int serverinfo_other_seen = 0;
Packit c4476c
Packit c4476c
/* This set from cmdline */
Packit c4476c
static int custom_ext = 0;
Packit c4476c
Packit c4476c
/* This set based on extension callbacks */
Packit c4476c
static int custom_ext_error = 0;
Packit c4476c
Packit c4476c
static int serverinfo_cli_parse_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                   const unsigned char *in, size_t inlen,
Packit c4476c
                                   int *al, void *arg)
Packit c4476c
{
Packit c4476c
    if (ext_type == TLSEXT_TYPE_signed_certificate_timestamp)
Packit c4476c
        serverinfo_sct_seen++;
Packit c4476c
    else if (ext_type == TACK_EXT_TYPE)
Packit c4476c
        serverinfo_tack_seen++;
Packit c4476c
    else
Packit c4476c
        serverinfo_other_seen++;
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int verify_serverinfo(void)
Packit c4476c
{
Packit c4476c
    if (serverinfo_sct != serverinfo_sct_seen)
Packit c4476c
        return -1;
Packit c4476c
    if (serverinfo_tack != serverinfo_tack_seen)
Packit c4476c
        return -1;
Packit c4476c
    if (serverinfo_other_seen)
Packit c4476c
        return -1;
Packit c4476c
    return 0;
Packit c4476c
}
Packit c4476c
Packit c4476c
/*-
Packit c4476c
 * Four test cases for custom extensions:
Packit c4476c
 * 0 - no ClientHello extension or ServerHello response
Packit c4476c
 * 1 - ClientHello with "abc", no response
Packit c4476c
 * 2 - ClientHello with "abc", empty response
Packit c4476c
 * 3 - ClientHello with "abc", "defg" response
Packit c4476c
 */
Packit c4476c
Packit c4476c
static int custom_ext_0_cli_add_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                   const unsigned char **out,
Packit c4476c
                                   size_t *outlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    if (ext_type != CUSTOM_EXT_TYPE_0)
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    return 0;                   /* Don't send an extension */
Packit c4476c
}
Packit c4476c
Packit c4476c
static int custom_ext_0_cli_parse_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                     const unsigned char *in,
Packit c4476c
                                     size_t inlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int custom_ext_1_cli_add_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                   const unsigned char **out,
Packit c4476c
                                   size_t *outlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    if (ext_type != CUSTOM_EXT_TYPE_1)
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    *out = (const unsigned char *)custom_ext_cli_string;
Packit c4476c
    *outlen = strlen(custom_ext_cli_string);
Packit c4476c
    return 1;                   /* Send "abc" */
Packit c4476c
}
Packit c4476c
Packit c4476c
static int custom_ext_1_cli_parse_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                     const unsigned char *in,
Packit c4476c
                                     size_t inlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int custom_ext_2_cli_add_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                   const unsigned char **out,
Packit c4476c
                                   size_t *outlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    if (ext_type != CUSTOM_EXT_TYPE_2)
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    *out = (const unsigned char *)custom_ext_cli_string;
Packit c4476c
    *outlen = strlen(custom_ext_cli_string);
Packit c4476c
    return 1;                   /* Send "abc" */
Packit c4476c
}
Packit c4476c
Packit c4476c
static int custom_ext_2_cli_parse_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                     const unsigned char *in,
Packit c4476c
                                     size_t inlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    if (ext_type != CUSTOM_EXT_TYPE_2)
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    if (inlen != 0)
Packit c4476c
        custom_ext_error = 1;   /* Should be empty response */
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int custom_ext_3_cli_add_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                   const unsigned char **out,
Packit c4476c
                                   size_t *outlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    if (ext_type != CUSTOM_EXT_TYPE_3)
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    *out = (const unsigned char *)custom_ext_cli_string;
Packit c4476c
    *outlen = strlen(custom_ext_cli_string);
Packit c4476c
    return 1;                   /* Send "abc" */
Packit c4476c
}
Packit c4476c
Packit c4476c
static int custom_ext_3_cli_parse_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                     const unsigned char *in,
Packit c4476c
                                     size_t inlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    if (ext_type != CUSTOM_EXT_TYPE_3)
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    if (inlen != strlen(custom_ext_srv_string))
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    if (memcmp(custom_ext_srv_string, in, inlen) != 0)
Packit c4476c
        custom_ext_error = 1;   /* Check for "defg" */
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
/*
Packit c4476c
 * custom_ext_0_cli_add_cb returns 0 - the server won't receive a callback
Packit c4476c
 * for this extension
Packit c4476c
 */
Packit c4476c
static int custom_ext_0_srv_parse_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                     const unsigned char *in,
Packit c4476c
                                     size_t inlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    custom_ext_error = 1;
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
/* 'add' callbacks are only called if the 'parse' callback is called */
Packit c4476c
static int custom_ext_0_srv_add_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                   const unsigned char **out,
Packit c4476c
                                   size_t *outlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    /* Error: should not have been called */
Packit c4476c
    custom_ext_error = 1;
Packit c4476c
    return 0;                   /* Don't send an extension */
Packit c4476c
}
Packit c4476c
Packit c4476c
static int custom_ext_1_srv_parse_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                     const unsigned char *in,
Packit c4476c
                                     size_t inlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    if (ext_type != CUSTOM_EXT_TYPE_1)
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    /* Check for "abc" */
Packit c4476c
    if (inlen != strlen(custom_ext_cli_string))
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    if (memcmp(in, custom_ext_cli_string, inlen) != 0)
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int custom_ext_1_srv_add_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                   const unsigned char **out,
Packit c4476c
                                   size_t *outlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    return 0;                   /* Don't send an extension */
Packit c4476c
}
Packit c4476c
Packit c4476c
static int custom_ext_2_srv_parse_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                     const unsigned char *in,
Packit c4476c
                                     size_t inlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    if (ext_type != CUSTOM_EXT_TYPE_2)
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    /* Check for "abc" */
Packit c4476c
    if (inlen != strlen(custom_ext_cli_string))
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    if (memcmp(in, custom_ext_cli_string, inlen) != 0)
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int custom_ext_2_srv_add_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                   const unsigned char **out,
Packit c4476c
                                   size_t *outlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    *out = NULL;
Packit c4476c
    *outlen = 0;
Packit c4476c
    return 1;                   /* Send empty extension */
Packit c4476c
}
Packit c4476c
Packit c4476c
static int custom_ext_3_srv_parse_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                     const unsigned char *in,
Packit c4476c
                                     size_t inlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    if (ext_type != CUSTOM_EXT_TYPE_3)
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    /* Check for "abc" */
Packit c4476c
    if (inlen != strlen(custom_ext_cli_string))
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    if (memcmp(in, custom_ext_cli_string, inlen) != 0)
Packit c4476c
        custom_ext_error = 1;
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int custom_ext_3_srv_add_cb(SSL *s, unsigned int ext_type,
Packit c4476c
                                   const unsigned char **out,
Packit c4476c
                                   size_t *outlen, int *al, void *arg)
Packit c4476c
{
Packit c4476c
    *out = (const unsigned char *)custom_ext_srv_string;
Packit c4476c
    *outlen = strlen(custom_ext_srv_string);
Packit c4476c
    return 1;                   /* Send "defg" */
Packit c4476c
}
Packit c4476c
Packit c4476c
static char *cipher = NULL;
Packit c4476c
static char *ciphersuites = NULL;
Packit c4476c
static int verbose = 0;
Packit c4476c
static int debug = 0;
Packit c4476c
Packit c4476c
int doit_localhost(SSL *s_ssl, SSL *c_ssl, int family,
Packit c4476c
                   long bytes, clock_t *s_time, clock_t *c_time);
Packit c4476c
int doit_biopair(SSL *s_ssl, SSL *c_ssl, long bytes, clock_t *s_time,
Packit c4476c
                 clock_t *c_time);
Packit c4476c
int doit(SSL *s_ssl, SSL *c_ssl, long bytes);
Packit c4476c
Packit c4476c
static void sv_usage(void)
Packit c4476c
{
Packit c4476c
    fprintf(stderr, "usage: ssltest [args ...]\n");
Packit c4476c
    fprintf(stderr, "\n");
Packit c4476c
    fprintf(stderr, " -server_auth  - check server certificate\n");
Packit c4476c
    fprintf(stderr, " -client_auth  - do client authentication\n");
Packit c4476c
    fprintf(stderr, " -v            - more output\n");
Packit c4476c
    fprintf(stderr, " -d            - debug output\n");
Packit c4476c
    fprintf(stderr, " -reuse        - use session-id reuse\n");
Packit c4476c
    fprintf(stderr, " -num <val>    - number of connections to perform\n");
Packit c4476c
    fprintf(stderr,
Packit c4476c
            " -bytes <val>  - number of bytes to swap between client/server\n");
Packit c4476c
#ifndef OPENSSL_NO_DH
Packit c4476c
    fprintf(stderr,
Packit c4476c
            " -dhe512       - use 512 bit key for DHE (to test failure)\n");
Packit c4476c
    fprintf(stderr,
Packit c4476c
            " -dhe1024      - use 1024 bit key (safe prime) for DHE (default, no-op)\n");
Packit c4476c
    fprintf(stderr,
Packit c4476c
            " -dhe1024dsa   - use 1024 bit key (with 160-bit subprime) for DHE\n");
Packit c4476c
    fprintf(stderr, " -no_dhe       - disable DHE\n");
Packit c4476c
#endif
Packit c4476c
#ifndef OPENSSL_NO_EC
Packit c4476c
    fprintf(stderr, " -no_ecdhe     - disable ECDHE\nTODO(openssl-team): no_ecdhe was broken by auto ecdh. Make this work again.\n");
Packit c4476c
#endif
Packit c4476c
#ifndef OPENSSL_NO_PSK
Packit c4476c
    fprintf(stderr, " -psk arg      - PSK in hex (without 0x)\n");
Packit c4476c
#endif
Packit c4476c
#ifndef OPENSSL_NO_SSL3
Packit c4476c
    fprintf(stderr, " -ssl3         - use SSLv3\n");
Packit c4476c
#endif
Packit c4476c
#ifndef OPENSSL_NO_TLS1
Packit c4476c
    fprintf(stderr, " -tls1         - use TLSv1\n");
Packit c4476c
#endif
Packit c4476c
#ifndef OPENSSL_NO_DTLS
Packit c4476c
    fprintf(stderr, " -dtls         - use DTLS\n");
Packit c4476c
#ifndef OPENSSL_NO_DTLS1
Packit c4476c
    fprintf(stderr, " -dtls1        - use DTLSv1\n");
Packit c4476c
#endif
Packit c4476c
#ifndef OPENSSL_NO_DTLS1_2
Packit c4476c
    fprintf(stderr, " -dtls12       - use DTLSv1.2\n");
Packit c4476c
#endif
Packit c4476c
#endif
Packit c4476c
    fprintf(stderr, " -CApath arg   - PEM format directory of CA's\n");
Packit c4476c
    fprintf(stderr, " -CAfile arg   - PEM format file of CA's\n");
Packit c4476c
    fprintf(stderr, " -cert arg     - Server certificate file\n");
Packit c4476c
    fprintf(stderr,
Packit c4476c
            " -key arg      - Server key file (default: same as -cert)\n");
Packit c4476c
    fprintf(stderr, " -c_cert arg   - Client certificate file\n");
Packit c4476c
    fprintf(stderr,
Packit c4476c
            " -c_key arg    - Client key file (default: same as -c_cert)\n");
Packit c4476c
    fprintf(stderr, " -cipher arg   - The TLSv1.2 and below cipher list\n");
Packit c4476c
    fprintf(stderr, " -ciphersuites arg   - The TLSv1.3 ciphersuites\n");
Packit c4476c
    fprintf(stderr, " -bio_pair     - Use BIO pairs\n");
Packit c4476c
    fprintf(stderr, " -ipv4         - Use IPv4 connection on localhost\n");
Packit c4476c
    fprintf(stderr, " -ipv6         - Use IPv6 connection on localhost\n");
Packit c4476c
    fprintf(stderr, " -f            - Test even cases that can't work\n");
Packit c4476c
    fprintf(stderr,
Packit c4476c
            " -time         - measure processor time used by client and server\n");
Packit c4476c
    fprintf(stderr, " -zlib         - use zlib compression\n");
Packit c4476c
#ifndef OPENSSL_NO_NEXTPROTONEG
Packit c4476c
    fprintf(stderr, " -npn_client - have client side offer NPN\n");
Packit c4476c
    fprintf(stderr, " -npn_server - have server side offer NPN\n");
Packit c4476c
    fprintf(stderr, " -npn_server_reject - have server reject NPN\n");
Packit c4476c
#endif
Packit c4476c
    fprintf(stderr, " -serverinfo_file file - have server use this file\n");
Packit c4476c
    fprintf(stderr, " -serverinfo_sct  - have client offer and expect SCT\n");
Packit c4476c
    fprintf(stderr,
Packit c4476c
            " -serverinfo_tack - have client offer and expect TACK\n");
Packit c4476c
    fprintf(stderr,
Packit c4476c
            " -custom_ext - try various custom extension callbacks\n");
Packit c4476c
    fprintf(stderr, " -alpn_client <string> - have client side offer ALPN\n");
Packit c4476c
    fprintf(stderr, " -alpn_server <string> - have server side offer ALPN\n");
Packit c4476c
    fprintf(stderr, " -alpn_server1 <string> - alias for -alpn_server\n");
Packit c4476c
    fprintf(stderr, " -alpn_server2 <string> - have server side context 2 offer ALPN\n");
Packit c4476c
    fprintf(stderr,
Packit c4476c
            " -alpn_expected <string> - the ALPN protocol that should be negotiated\n");
Packit c4476c
    fprintf(stderr, " -server_min_proto <string> - Minimum version the server should support\n");
Packit c4476c
    fprintf(stderr, " -server_max_proto <string> - Maximum version the server should support\n");
Packit c4476c
    fprintf(stderr, " -client_min_proto <string> - Minimum version the client should support\n");
Packit c4476c
    fprintf(stderr, " -client_max_proto <string> - Maximum version the client should support\n");
Packit c4476c
    fprintf(stderr, " -should_negotiate <string> - The version that should be negotiated, fail-client or fail-server\n");
Packit c4476c
#ifndef OPENSSL_NO_CT
Packit c4476c
    fprintf(stderr, " -noct         - no certificate transparency\n");
Packit c4476c
    fprintf(stderr, " -requestct    - request certificate transparency\n");
Packit c4476c
    fprintf(stderr, " -requirect    - require certificate transparency\n");
Packit c4476c
#endif
Packit c4476c
    fprintf(stderr, " -sn_client <string>  - have client request this servername\n");
Packit c4476c
    fprintf(stderr, " -sn_server1 <string> - have server context 1 respond to this servername\n");
Packit c4476c
    fprintf(stderr, " -sn_server2 <string> - have server context 2 respond to this servername\n");
Packit c4476c
    fprintf(stderr, " -sn_expect1          - expected server 1\n");
Packit c4476c
    fprintf(stderr, " -sn_expect2          - expected server 2\n");
Packit c4476c
    fprintf(stderr, " -server_sess_out <file>    - Save the server session to a file\n");
Packit c4476c
    fprintf(stderr, " -server_sess_in <file>     - Read the server session from a file\n");
Packit c4476c
    fprintf(stderr, " -client_sess_out <file>    - Save the client session to a file\n");
Packit c4476c
    fprintf(stderr, " -client_sess_in <file>     - Read the client session from a file\n");
Packit c4476c
    fprintf(stderr, " -should_reuse <number>     - The expected state of reusing the session\n");
Packit c4476c
    fprintf(stderr, " -no_ticket    - do not issue TLS session ticket\n");
Packit c4476c
}
Packit c4476c
Packit c4476c
static void print_key_details(BIO *out, EVP_PKEY *key)
Packit c4476c
{
Packit c4476c
    int keyid = EVP_PKEY_id(key);
Packit c4476c
#ifndef OPENSSL_NO_EC
Packit c4476c
    if (keyid == EVP_PKEY_EC) {
Packit c4476c
        EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
Packit c4476c
        int nid;
Packit c4476c
        const char *cname;
Packit c4476c
        nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
Packit c4476c
        EC_KEY_free(ec);
Packit c4476c
        cname = EC_curve_nid2nist(nid);
Packit c4476c
        if (!cname)
Packit c4476c
            cname = OBJ_nid2sn(nid);
Packit c4476c
        BIO_printf(out, "%d bits EC (%s)", EVP_PKEY_bits(key), cname);
Packit c4476c
    } else
Packit c4476c
#endif
Packit c4476c
    {
Packit c4476c
        const char *algname;
Packit c4476c
        switch (keyid) {
Packit c4476c
        case EVP_PKEY_RSA:
Packit c4476c
            algname = "RSA";
Packit c4476c
            break;
Packit c4476c
        case EVP_PKEY_DSA:
Packit c4476c
            algname = "DSA";
Packit c4476c
            break;
Packit c4476c
        case EVP_PKEY_DH:
Packit c4476c
            algname = "DH";
Packit c4476c
            break;
Packit c4476c
        default:
Packit c4476c
            algname = OBJ_nid2sn(keyid);
Packit c4476c
            break;
Packit c4476c
        }
Packit c4476c
        BIO_printf(out, "%d bits %s", EVP_PKEY_bits(key), algname);
Packit c4476c
    }
Packit c4476c
}
Packit c4476c
Packit c4476c
static void print_details(SSL *c_ssl, const char *prefix)
Packit c4476c
{
Packit c4476c
    const SSL_CIPHER *ciph;
Packit c4476c
    int mdnid;
Packit c4476c
    X509 *cert;
Packit c4476c
    EVP_PKEY *pkey;
Packit c4476c
Packit c4476c
    ciph = SSL_get_current_cipher(c_ssl);
Packit c4476c
    BIO_printf(bio_stdout, "%s%s, cipher %s %s",
Packit c4476c
               prefix,
Packit c4476c
               SSL_get_version(c_ssl),
Packit c4476c
               SSL_CIPHER_get_version(ciph), SSL_CIPHER_get_name(ciph));
Packit c4476c
    cert = SSL_get_peer_certificate(c_ssl);
Packit c4476c
    if (cert != NULL) {
Packit c4476c
        EVP_PKEY* pubkey = X509_get0_pubkey(cert);
Packit c4476c
Packit c4476c
        if (pubkey != NULL) {
Packit c4476c
            BIO_puts(bio_stdout, ", ");
Packit c4476c
            print_key_details(bio_stdout, pubkey);
Packit c4476c
        }
Packit c4476c
        X509_free(cert);
Packit c4476c
    }
Packit c4476c
    if (SSL_get_peer_tmp_key(c_ssl, &pkey)) {
Packit c4476c
        BIO_puts(bio_stdout, ", temp key: ");
Packit c4476c
        print_key_details(bio_stdout, pkey);
Packit c4476c
        EVP_PKEY_free(pkey);
Packit c4476c
    }
Packit c4476c
    if (SSL_get_peer_signature_nid(c_ssl, &mdnid))
Packit c4476c
        BIO_printf(bio_stdout, ", digest=%s", OBJ_nid2sn(mdnid));
Packit c4476c
    BIO_printf(bio_stdout, "\n");
Packit c4476c
}
Packit c4476c
Packit c4476c
/*
Packit c4476c
 * protocol_from_string - converts a protocol version string to a number
Packit c4476c
 *
Packit c4476c
 * Returns -1 on failure or the version on success
Packit c4476c
 */
Packit c4476c
static int protocol_from_string(const char *value)
Packit c4476c
{
Packit c4476c
    struct protocol_versions {
Packit c4476c
        const char *name;
Packit c4476c
        int version;
Packit c4476c
    };
Packit c4476c
    static const struct protocol_versions versions[] = {
Packit c4476c
        {"ssl3", SSL3_VERSION},
Packit c4476c
        {"tls1", TLS1_VERSION},
Packit c4476c
        {"tls1.1", TLS1_1_VERSION},
Packit c4476c
        {"tls1.2", TLS1_2_VERSION},
Packit c4476c
        {"tls1.3", TLS1_3_VERSION},
Packit c4476c
        {"dtls1", DTLS1_VERSION},
Packit c4476c
        {"dtls1.2", DTLS1_2_VERSION}};
Packit c4476c
    size_t i;
Packit c4476c
    size_t n = OSSL_NELEM(versions);
Packit c4476c
Packit c4476c
    for (i = 0; i < n; i++)
Packit c4476c
        if (strcmp(versions[i].name, value) == 0)
Packit c4476c
            return versions[i].version;
Packit c4476c
    return -1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static SSL_SESSION *read_session(const char *filename)
Packit c4476c
{
Packit c4476c
    SSL_SESSION *sess;
Packit c4476c
    BIO *f = BIO_new_file(filename, "r");
Packit c4476c
Packit c4476c
    if (f == NULL) {
Packit c4476c
        BIO_printf(bio_err, "Can't open session file %s\n", filename);
Packit c4476c
        ERR_print_errors(bio_err);
Packit c4476c
        return NULL;
Packit c4476c
    }
Packit c4476c
    sess = PEM_read_bio_SSL_SESSION(f, NULL, 0, NULL);
Packit c4476c
    if (sess == NULL) {
Packit c4476c
        BIO_printf(bio_err, "Can't parse session file %s\n", filename);
Packit c4476c
        ERR_print_errors(bio_err);
Packit c4476c
    }
Packit c4476c
    BIO_free(f);
Packit c4476c
    return sess;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int write_session(const char *filename, SSL_SESSION *sess)
Packit c4476c
{
Packit c4476c
    BIO *f = BIO_new_file(filename, "w");
Packit c4476c
Packit c4476c
    if (sess == NULL) {
Packit c4476c
        BIO_printf(bio_err, "No session information\n");
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
    if (f == NULL) {
Packit c4476c
        BIO_printf(bio_err, "Can't open session file %s\n", filename);
Packit c4476c
        ERR_print_errors(bio_err);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
    PEM_write_bio_SSL_SESSION(f, sess);
Packit c4476c
    BIO_free(f);
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
/*
Packit c4476c
 * set_protocol_version - Sets protocol version minimum or maximum
Packit c4476c
 *
Packit c4476c
 * Returns 0 on failure and 1 on success
Packit c4476c
 */
Packit c4476c
static int set_protocol_version(const char *version, SSL *ssl, int setting)
Packit c4476c
{
Packit c4476c
    if (version != NULL) {
Packit c4476c
        int ver = protocol_from_string(version);
Packit c4476c
        if (ver < 0) {
Packit c4476c
            BIO_printf(bio_err, "Error parsing: %s\n", version);
Packit c4476c
            return 0;
Packit c4476c
        }
Packit c4476c
        return SSL_ctrl(ssl, setting, ver, NULL);
Packit c4476c
    }
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
int main(int argc, char *argv[])
Packit c4476c
{
Packit c4476c
    const char *CApath = NULL, *CAfile = NULL;
Packit c4476c
    int badop = 0;
Packit c4476c
    enum { BIO_MEM, BIO_PAIR, BIO_IPV4, BIO_IPV6 } bio_type = BIO_MEM;
Packit c4476c
    int force = 0;
Packit c4476c
    int dtls1 = 0, dtls12 = 0, dtls = 0, tls1 = 0, tls1_2 = 0, ssl3 = 0;
Packit c4476c
    int ret = EXIT_FAILURE;
Packit c4476c
    int client_auth = 0;
Packit c4476c
    int server_auth = 0, i;
Packit c4476c
    struct app_verify_arg app_verify_arg =
Packit c4476c
        { APP_CALLBACK_STRING, 0 };
Packit c4476c
    char *p;
Packit c4476c
    SSL_CTX *c_ctx = NULL;
Packit c4476c
    const SSL_METHOD *meth = NULL;
Packit c4476c
    SSL *c_ssl, *s_ssl;
Packit c4476c
    int number = 1, reuse = 0;
Packit c4476c
    int should_reuse = -1;
Packit c4476c
    int no_ticket = 0;
Packit c4476c
    long bytes = 256L;
Packit c4476c
#ifndef OPENSSL_NO_DH
Packit c4476c
    DH *dh;
Packit c4476c
    int dhe512 = 0, dhe1024dsa = 0;
Packit c4476c
#endif
Packit c4476c
    int no_dhe = 0;
Packit c4476c
    int no_psk = 0;
Packit c4476c
    int print_time = 0;
Packit c4476c
    clock_t s_time = 0, c_time = 0;
Packit c4476c
#ifndef OPENSSL_NO_COMP
Packit c4476c
    int n, comp = 0;
Packit c4476c
    COMP_METHOD *cm = NULL;
Packit c4476c
    STACK_OF(SSL_COMP) *ssl_comp_methods = NULL;
Packit c4476c
#endif
Packit c4476c
    int no_protocol;
Packit c4476c
    int min_version = 0, max_version = 0;
Packit c4476c
#ifndef OPENSSL_NO_CT
Packit c4476c
    /*
Packit c4476c
     * Disable CT validation by default, because it will interfere with
Packit c4476c
     * anything using custom extension handlers to deal with SCT extensions.
Packit c4476c
     */
Packit c4476c
    int ct_validation = 0;
Packit c4476c
#endif
Packit c4476c
    SSL_CONF_CTX *s_cctx = NULL, *c_cctx = NULL, *s_cctx2 = NULL;
Packit c4476c
    STACK_OF(OPENSSL_STRING) *conf_args = NULL;
Packit c4476c
    char *arg = NULL, *argn = NULL;
Packit c4476c
Packit c4476c
    verbose = 0;
Packit c4476c
    debug = 0;
Packit c4476c
Packit c4476c
    bio_err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
Packit c4476c
Packit c4476c
    p = getenv("OPENSSL_DEBUG_MEMORY");
Packit c4476c
    if (p != NULL && strcmp(p, "on") == 0)
Packit c4476c
        CRYPTO_set_mem_debug(1);
Packit c4476c
    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
Packit c4476c
Packit c4476c
    bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE | BIO_FP_TEXT);
Packit c4476c
Packit c4476c
    s_cctx = SSL_CONF_CTX_new();
Packit c4476c
    s_cctx2 = SSL_CONF_CTX_new();
Packit c4476c
    c_cctx = SSL_CONF_CTX_new();
Packit c4476c
Packit c4476c
    if (!s_cctx || !c_cctx || !s_cctx2) {
Packit c4476c
        ERR_print_errors(bio_err);
Packit c4476c
        goto end;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    SSL_CONF_CTX_set_flags(s_cctx,
Packit c4476c
                           SSL_CONF_FLAG_CMDLINE | SSL_CONF_FLAG_SERVER |
Packit c4476c
                           SSL_CONF_FLAG_CERTIFICATE |
Packit c4476c
                           SSL_CONF_FLAG_REQUIRE_PRIVATE);
Packit c4476c
    SSL_CONF_CTX_set_flags(s_cctx2,
Packit c4476c
                           SSL_CONF_FLAG_CMDLINE | SSL_CONF_FLAG_SERVER |
Packit c4476c
                           SSL_CONF_FLAG_CERTIFICATE |
Packit c4476c
                           SSL_CONF_FLAG_REQUIRE_PRIVATE);
Packit c4476c
    if (!SSL_CONF_CTX_set1_prefix(s_cctx, "-s_")) {
Packit c4476c
        ERR_print_errors(bio_err);
Packit c4476c
        goto end;
Packit c4476c
    }
Packit c4476c
    if (!SSL_CONF_CTX_set1_prefix(s_cctx2, "-s_")) {
Packit c4476c
        ERR_print_errors(bio_err);
Packit c4476c
        goto end;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    SSL_CONF_CTX_set_flags(c_cctx,
Packit c4476c
                           SSL_CONF_FLAG_CMDLINE | SSL_CONF_FLAG_CLIENT |
Packit c4476c
                           SSL_CONF_FLAG_CERTIFICATE |
Packit c4476c
                           SSL_CONF_FLAG_REQUIRE_PRIVATE);
Packit c4476c
    if (!SSL_CONF_CTX_set1_prefix(c_cctx, "-c_")) {
Packit c4476c
        ERR_print_errors(bio_err);
Packit c4476c
        goto end;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    argc--;
Packit c4476c
    argv++;
Packit c4476c
Packit c4476c
    while (argc >= 1) {
Packit c4476c
        if (strcmp(*argv, "-F") == 0) {
Packit c4476c
            fprintf(stderr,
Packit c4476c
                    "not compiled with FIPS support, so exiting without running.\n");
Packit c4476c
            EXIT(0);
Packit c4476c
        } else if (strcmp(*argv, "-server_auth") == 0)
Packit c4476c
            server_auth = 1;
Packit c4476c
        else if (strcmp(*argv, "-client_auth") == 0)
Packit c4476c
            client_auth = 1;
Packit c4476c
        else if (strcmp(*argv, "-v") == 0)
Packit c4476c
            verbose = 1;
Packit c4476c
        else if (strcmp(*argv, "-d") == 0)
Packit c4476c
            debug = 1;
Packit c4476c
        else if (strcmp(*argv, "-reuse") == 0)
Packit c4476c
            reuse = 1;
Packit c4476c
        else if (strcmp(*argv, "-dhe512") == 0) {
Packit c4476c
#ifndef OPENSSL_NO_DH
Packit c4476c
            dhe512 = 1;
Packit c4476c
#else
Packit c4476c
            fprintf(stderr,
Packit c4476c
                    "ignoring -dhe512, since I'm compiled without DH\n");
Packit c4476c
#endif
Packit c4476c
        } else if (strcmp(*argv, "-dhe1024dsa") == 0) {
Packit c4476c
#ifndef OPENSSL_NO_DH
Packit c4476c
            dhe1024dsa = 1;
Packit c4476c
#else
Packit c4476c
            fprintf(stderr,
Packit c4476c
                    "ignoring -dhe1024dsa, since I'm compiled without DH\n");
Packit c4476c
#endif
Packit c4476c
        } else if (strcmp(*argv, "-no_dhe") == 0)
Packit c4476c
            no_dhe = 1;
Packit c4476c
        else if (strcmp(*argv, "-no_ecdhe") == 0)
Packit c4476c
            /* obsolete */;
Packit c4476c
        else if (strcmp(*argv, "-psk") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            psk_key = *(++argv);
Packit c4476c
#ifndef OPENSSL_NO_PSK
Packit c4476c
            if (strspn(psk_key, "abcdefABCDEF1234567890") != strlen(psk_key)) {
Packit c4476c
                BIO_printf(bio_err, "Not a hex number '%s'\n", *argv);
Packit c4476c
                goto bad;
Packit c4476c
            }
Packit c4476c
#else
Packit c4476c
            no_psk = 1;
Packit c4476c
#endif
Packit c4476c
        }
Packit c4476c
        else if (strcmp(*argv, "-tls1_2") == 0) {
Packit c4476c
            tls1_2 = 1;
Packit c4476c
        } else if (strcmp(*argv, "-tls1") == 0) {
Packit c4476c
            tls1 = 1;
Packit c4476c
        } else if (strcmp(*argv, "-ssl3") == 0) {
Packit c4476c
            ssl3 = 1;
Packit c4476c
        } else if (strcmp(*argv, "-dtls1") == 0) {
Packit c4476c
            dtls1 = 1;
Packit c4476c
        } else if (strcmp(*argv, "-dtls12") == 0) {
Packit c4476c
            dtls12 = 1;
Packit c4476c
        } else if (strcmp(*argv, "-dtls") == 0) {
Packit c4476c
            dtls = 1;
Packit c4476c
        } else if (strncmp(*argv, "-num", 4) == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            number = atoi(*(++argv));
Packit c4476c
            if (number == 0)
Packit c4476c
                number = 1;
Packit c4476c
        } else if (strcmp(*argv, "-bytes") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            bytes = atol(*(++argv));
Packit c4476c
            if (bytes == 0L)
Packit c4476c
                bytes = 1L;
Packit c4476c
            i = strlen(argv[0]);
Packit c4476c
            if (argv[0][i - 1] == 'k')
Packit c4476c
                bytes *= 1024L;
Packit c4476c
            if (argv[0][i - 1] == 'm')
Packit c4476c
                bytes *= 1024L * 1024L;
Packit c4476c
        } else if (strcmp(*argv, "-cipher") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            cipher = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-ciphersuites") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            ciphersuites = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-CApath") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            CApath = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-CAfile") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            CAfile = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-bio_pair") == 0) {
Packit c4476c
            bio_type = BIO_PAIR;
Packit c4476c
        }
Packit c4476c
#ifndef OPENSSL_NO_SOCK
Packit c4476c
        else if (strcmp(*argv, "-ipv4") == 0) {
Packit c4476c
            bio_type = BIO_IPV4;
Packit c4476c
        } else if (strcmp(*argv, "-ipv6") == 0) {
Packit c4476c
            bio_type = BIO_IPV6;
Packit c4476c
        }
Packit c4476c
#endif
Packit c4476c
        else if (strcmp(*argv, "-f") == 0) {
Packit c4476c
            force = 1;
Packit c4476c
        } else if (strcmp(*argv, "-time") == 0) {
Packit c4476c
            print_time = 1;
Packit c4476c
        }
Packit c4476c
#ifndef OPENSSL_NO_CT
Packit c4476c
        else if (strcmp(*argv, "-noct") == 0) {
Packit c4476c
            ct_validation = 0;
Packit c4476c
        }
Packit c4476c
        else if (strcmp(*argv, "-ct") == 0) {
Packit c4476c
            ct_validation = 1;
Packit c4476c
        }
Packit c4476c
#endif
Packit c4476c
#ifndef OPENSSL_NO_COMP
Packit c4476c
        else if (strcmp(*argv, "-zlib") == 0) {
Packit c4476c
            comp = COMP_ZLIB;
Packit c4476c
        }
Packit c4476c
#endif
Packit c4476c
        else if (strcmp(*argv, "-app_verify") == 0) {
Packit c4476c
            app_verify_arg.app_verify = 1;
Packit c4476c
        }
Packit c4476c
#ifndef OPENSSL_NO_NEXTPROTONEG
Packit c4476c
          else if (strcmp(*argv, "-npn_client") == 0) {
Packit c4476c
            npn_client = 1;
Packit c4476c
        } else if (strcmp(*argv, "-npn_server") == 0) {
Packit c4476c
            npn_server = 1;
Packit c4476c
        } else if (strcmp(*argv, "-npn_server_reject") == 0) {
Packit c4476c
            npn_server_reject = 1;
Packit c4476c
        }
Packit c4476c
#endif
Packit c4476c
        else if (strcmp(*argv, "-serverinfo_sct") == 0) {
Packit c4476c
            serverinfo_sct = 1;
Packit c4476c
        } else if (strcmp(*argv, "-serverinfo_tack") == 0) {
Packit c4476c
            serverinfo_tack = 1;
Packit c4476c
        } else if (strcmp(*argv, "-serverinfo_file") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            serverinfo_file = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-custom_ext") == 0) {
Packit c4476c
            custom_ext = 1;
Packit c4476c
        } else if (strcmp(*argv, "-alpn_client") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            alpn_client = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-alpn_server") == 0 ||
Packit c4476c
                   strcmp(*argv, "-alpn_server1") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            alpn_server = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-alpn_server2") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            alpn_server2 = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-alpn_expected") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            alpn_expected = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-server_min_proto") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            server_min_proto = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-server_max_proto") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            server_max_proto = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-client_min_proto") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            client_min_proto = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-client_max_proto") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            client_max_proto = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-should_negotiate") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            should_negotiate = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-sn_client") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            sn_client = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-sn_server1") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            sn_server1 = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-sn_server2") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            sn_server2 = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-sn_expect1") == 0) {
Packit c4476c
            sn_expect = 1;
Packit c4476c
        } else if (strcmp(*argv, "-sn_expect2") == 0) {
Packit c4476c
            sn_expect = 2;
Packit c4476c
        } else if (strcmp(*argv, "-server_sess_out") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            server_sess_out = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-server_sess_in") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            server_sess_in = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-client_sess_out") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            client_sess_out = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-client_sess_in") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            client_sess_in = *(++argv);
Packit c4476c
        } else if (strcmp(*argv, "-should_reuse") == 0) {
Packit c4476c
            if (--argc < 1)
Packit c4476c
                goto bad;
Packit c4476c
            should_reuse = !!atoi(*(++argv));
Packit c4476c
        } else if (strcmp(*argv, "-no_ticket") == 0) {
Packit c4476c
            no_ticket = 1;
Packit c4476c
        } else {
Packit c4476c
            int rv;
Packit c4476c
            arg = argv[0];
Packit c4476c
            argn = argv[1];
Packit c4476c
            /* Try to process command using SSL_CONF */
Packit c4476c
            rv = SSL_CONF_cmd_argv(c_cctx, &argc, &argv);
Packit c4476c
            /* If not processed try server */
Packit c4476c
            if (rv == 0)
Packit c4476c
                rv = SSL_CONF_cmd_argv(s_cctx, &argc, &argv);
Packit c4476c
            /* Recognised: store it for later use */
Packit c4476c
            if (rv > 0) {
Packit c4476c
                if (rv == 1)
Packit c4476c
                    argn = NULL;
Packit c4476c
                if (!conf_args) {
Packit c4476c
                    conf_args = sk_OPENSSL_STRING_new_null();
Packit c4476c
                    if (!conf_args)
Packit c4476c
                        goto end;
Packit c4476c
                }
Packit c4476c
                if (!sk_OPENSSL_STRING_push(conf_args, arg))
Packit c4476c
                    goto end;
Packit c4476c
                if (!sk_OPENSSL_STRING_push(conf_args, argn))
Packit c4476c
                    goto end;
Packit c4476c
                continue;
Packit c4476c
            }
Packit c4476c
            if (rv == -3)
Packit c4476c
                BIO_printf(bio_err, "Missing argument for %s\n", arg);
Packit c4476c
            else if (rv < 0)
Packit c4476c
                BIO_printf(bio_err, "Error with command %s\n", arg);
Packit c4476c
            else if (rv == 0)
Packit c4476c
                BIO_printf(bio_err, "unknown option %s\n", arg);
Packit c4476c
            badop = 1;
Packit c4476c
            break;
Packit c4476c
        }
Packit c4476c
        argc--;
Packit c4476c
        argv++;
Packit c4476c
    }
Packit c4476c
    if (badop) {
Packit c4476c
 bad:
Packit c4476c
        sv_usage();
Packit c4476c
        goto end;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (ssl3 + tls1 + tls1_2 + dtls + dtls1 + dtls12 > 1) {
Packit c4476c
        fprintf(stderr, "At most one of -ssl3, -tls1, -tls1_2, -dtls, -dtls1 or -dtls12 should "
Packit c4476c
                "be requested.\n");
Packit c4476c
        EXIT(1);
Packit c4476c
    }
Packit c4476c
Packit c4476c
#ifdef OPENSSL_NO_SSL3
Packit c4476c
    if (ssl3)
Packit c4476c
        no_protocol = 1;
Packit c4476c
    else
Packit c4476c
#endif
Packit c4476c
#ifdef OPENSSL_NO_TLS1
Packit c4476c
    if (tls1)
Packit c4476c
        no_protocol = 1;
Packit c4476c
    else
Packit c4476c
#endif
Packit c4476c
#ifdef OPENSSL_NO_TLS1_2
Packit c4476c
    if (tls1_2)
Packit c4476c
        no_protocol = 1;
Packit c4476c
    else
Packit c4476c
#endif
Packit c4476c
#if defined(OPENSSL_NO_DTLS) || defined(OPENSSL_NO_DTLS1)
Packit c4476c
    if (dtls1)
Packit c4476c
        no_protocol = 1;
Packit c4476c
    else
Packit c4476c
#endif
Packit c4476c
#if defined(OPENSSL_NO_DTLS) || defined(OPENSSL_NO_DTLS1_2)
Packit c4476c
    if (dtls12)
Packit c4476c
        no_protocol = 1;
Packit c4476c
    else
Packit c4476c
#endif
Packit c4476c
        no_protocol = 0;
Packit c4476c
Packit c4476c
    /*
Packit c4476c
     * Testing was requested for a compiled-out protocol (e.g. SSLv3).
Packit c4476c
     * Ideally, we would error out, but the generic test wrapper can't know
Packit c4476c
     * when to expect failure. So we do nothing and return success.
Packit c4476c
     */
Packit c4476c
    if (no_protocol) {
Packit c4476c
        fprintf(stderr, "Testing was requested for a disabled protocol. "
Packit c4476c
                "Skipping tests.\n");
Packit c4476c
        ret = EXIT_SUCCESS;
Packit c4476c
        goto end;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (!ssl3 && !tls1 && !tls1_2 && !dtls && !dtls1 && !dtls12 && number > 1
Packit c4476c
            && !reuse && !force) {
Packit c4476c
        fprintf(stderr, "This case cannot work.  Use -f to perform "
Packit c4476c
                "the test anyway (and\n-d to see what happens), "
Packit c4476c
                "or add one of -ssl3, -tls1, -tls1_2, -dtls, -dtls1, -dtls12, -reuse\n"
Packit c4476c
                "to avoid protocol mismatch.\n");
Packit c4476c
        EXIT(1);
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (print_time) {
Packit c4476c
        if (bio_type != BIO_PAIR) {
Packit c4476c
            fprintf(stderr, "Using BIO pair (-bio_pair)\n");
Packit c4476c
            bio_type = BIO_PAIR;
Packit c4476c
        }
Packit c4476c
        if (number < 50 && !force)
Packit c4476c
            fprintf(stderr,
Packit c4476c
                    "Warning: For accurate timings, use more connections (e.g. -num 1000)\n");
Packit c4476c
    }
Packit c4476c
Packit c4476c
#ifndef OPENSSL_NO_COMP
Packit c4476c
    if (comp == COMP_ZLIB)
Packit c4476c
        cm = COMP_zlib();
Packit c4476c
    if (cm != NULL) {
Packit c4476c
        if (COMP_get_type(cm) != NID_undef) {
Packit c4476c
            if (SSL_COMP_add_compression_method(comp, cm) != 0) {
Packit c4476c
                fprintf(stderr, "Failed to add compression method\n");
Packit c4476c
                ERR_print_errors_fp(stderr);
Packit c4476c
            }
Packit c4476c
        } else {
Packit c4476c
            fprintf(stderr,
Packit c4476c
                    "Warning: %s compression not supported\n",
Packit c4476c
                    comp == COMP_ZLIB ? "zlib" : "unknown");
Packit c4476c
            ERR_print_errors_fp(stderr);
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
    ssl_comp_methods = SSL_COMP_get_compression_methods();
Packit c4476c
    n = sk_SSL_COMP_num(ssl_comp_methods);
Packit c4476c
    if (n) {
Packit c4476c
        int j;
Packit c4476c
        printf("Available compression methods:");
Packit c4476c
        for (j = 0; j < n; j++) {
Packit c4476c
            SSL_COMP *c = sk_SSL_COMP_value(ssl_comp_methods, j);
Packit c4476c
            printf("  %s:%d", SSL_COMP_get0_name(c), SSL_COMP_get_id(c));
Packit c4476c
        }
Packit c4476c
        printf("\n");
Packit c4476c
    }
Packit c4476c
#endif
Packit c4476c
Packit c4476c
#ifndef OPENSSL_NO_TLS
Packit c4476c
    meth = TLS_method();
Packit c4476c
    if (ssl3) {
Packit c4476c
        min_version = SSL3_VERSION;
Packit c4476c
        max_version = SSL3_VERSION;
Packit c4476c
    } else if (tls1) {
Packit c4476c
        min_version = TLS1_VERSION;
Packit c4476c
        max_version = TLS1_VERSION;
Packit c4476c
    } else if (tls1_2) {
Packit c4476c
        min_version = TLS1_2_VERSION;
Packit c4476c
        max_version = TLS1_2_VERSION;
Packit c4476c
    } else {
Packit c4476c
        min_version = SSL3_VERSION;
Packit c4476c
        max_version = TLS_MAX_VERSION;
Packit c4476c
    }
Packit c4476c
#endif
Packit c4476c
#ifndef OPENSSL_NO_DTLS
Packit c4476c
    if (dtls || dtls1 || dtls12) {
Packit c4476c
        meth = DTLS_method();
Packit c4476c
        if (dtls1) {
Packit c4476c
            min_version = DTLS1_VERSION;
Packit c4476c
            max_version = DTLS1_VERSION;
Packit c4476c
        } else if (dtls12) {
Packit c4476c
            min_version = DTLS1_2_VERSION;
Packit c4476c
            max_version = DTLS1_2_VERSION;
Packit c4476c
        } else {
Packit c4476c
            min_version = DTLS_MIN_VERSION;
Packit c4476c
            max_version = DTLS_MAX_VERSION;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
#endif
Packit c4476c
Packit c4476c
    c_ctx = SSL_CTX_new(meth);
Packit c4476c
    s_ctx = SSL_CTX_new(meth);
Packit c4476c
    s_ctx2 = SSL_CTX_new(meth); /* no SSL_CTX_dup! */
Packit c4476c
    if ((c_ctx == NULL) || (s_ctx == NULL) || (s_ctx2 == NULL)) {
Packit c4476c
        ERR_print_errors(bio_err);
Packit c4476c
        goto end;
Packit c4476c
    }
Packit c4476c
    /*
Packit c4476c
     * Since we will use low security ciphersuites and keys for testing set
Packit c4476c
     * security level to zero by default. Tests can override this by adding
Packit c4476c
     * "@SECLEVEL=n" to the cipher string.
Packit c4476c
     */
Packit c4476c
    SSL_CTX_set_security_level(c_ctx, 0);
Packit c4476c
    SSL_CTX_set_security_level(s_ctx, 0);
Packit c4476c
    SSL_CTX_set_security_level(s_ctx2, 0);
Packit c4476c
Packit c4476c
    if (no_ticket) {
Packit c4476c
        SSL_CTX_set_options(c_ctx, SSL_OP_NO_TICKET);
Packit c4476c
        SSL_CTX_set_options(s_ctx, SSL_OP_NO_TICKET);
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (SSL_CTX_set_min_proto_version(c_ctx, min_version) == 0)
Packit c4476c
        goto end;
Packit c4476c
    if (SSL_CTX_set_max_proto_version(c_ctx, max_version) == 0)
Packit c4476c
        goto end;
Packit c4476c
    if (SSL_CTX_set_min_proto_version(s_ctx, min_version) == 0)
Packit c4476c
        goto end;
Packit c4476c
    if (SSL_CTX_set_max_proto_version(s_ctx, max_version) == 0)
Packit c4476c
        goto end;
Packit c4476c
Packit c4476c
    if (cipher != NULL) {
Packit c4476c
        if (strcmp(cipher, "") == 0) {
Packit c4476c
            if (!SSL_CTX_set_cipher_list(c_ctx, cipher)) {
Packit c4476c
                if (ERR_GET_REASON(ERR_peek_error()) == SSL_R_NO_CIPHER_MATCH) {
Packit c4476c
                    ERR_clear_error();
Packit c4476c
                } else {
Packit c4476c
                    ERR_print_errors(bio_err);
Packit c4476c
                    goto end;
Packit c4476c
                }
Packit c4476c
            } else {
Packit c4476c
                /* Should have failed when clearing all TLSv1.2 ciphers. */
Packit c4476c
                fprintf(stderr, "CLEARING ALL TLSv1.2 CIPHERS SHOULD FAIL\n");
Packit c4476c
                goto end;
Packit c4476c
            }
Packit c4476c
Packit c4476c
            if (!SSL_CTX_set_cipher_list(s_ctx, cipher)) {
Packit c4476c
                if (ERR_GET_REASON(ERR_peek_error()) == SSL_R_NO_CIPHER_MATCH) {
Packit c4476c
                    ERR_clear_error();
Packit c4476c
                } else {
Packit c4476c
                    ERR_print_errors(bio_err);
Packit c4476c
                    goto end;
Packit c4476c
                }
Packit c4476c
            } else {
Packit c4476c
                /* Should have failed when clearing all TLSv1.2 ciphers. */
Packit c4476c
                fprintf(stderr, "CLEARING ALL TLSv1.2 CIPHERS SHOULD FAIL\n");
Packit c4476c
                goto end;
Packit c4476c
            }
Packit c4476c
Packit c4476c
            if (!SSL_CTX_set_cipher_list(s_ctx2, cipher)) {
Packit c4476c
                if (ERR_GET_REASON(ERR_peek_error()) == SSL_R_NO_CIPHER_MATCH) {
Packit c4476c
                    ERR_clear_error();
Packit c4476c
                } else {
Packit c4476c
                    ERR_print_errors(bio_err);
Packit c4476c
                    goto end;
Packit c4476c
                }
Packit c4476c
            } else {
Packit c4476c
                /* Should have failed when clearing all TLSv1.2 ciphers. */
Packit c4476c
                fprintf(stderr, "CLEARING ALL TLSv1.2 CIPHERS SHOULD FAIL\n");
Packit c4476c
                goto end;
Packit c4476c
            }
Packit c4476c
        } else {
Packit c4476c
            if (!SSL_CTX_set_cipher_list(c_ctx, cipher)
Packit c4476c
                    || !SSL_CTX_set_cipher_list(s_ctx, cipher)
Packit c4476c
                    || !SSL_CTX_set_cipher_list(s_ctx2, cipher)) {
Packit c4476c
                ERR_print_errors(bio_err);
Packit c4476c
                goto end;
Packit c4476c
            }
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
    if (ciphersuites != NULL) {
Packit c4476c
        if (!SSL_CTX_set_ciphersuites(c_ctx, ciphersuites)
Packit c4476c
            || !SSL_CTX_set_ciphersuites(s_ctx, ciphersuites)
Packit c4476c
            || !SSL_CTX_set_ciphersuites(s_ctx2, ciphersuites)) {
Packit c4476c
            ERR_print_errors(bio_err);
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
Packit c4476c
#ifndef OPENSSL_NO_CT
Packit c4476c
    if (ct_validation &&
Packit c4476c
        !SSL_CTX_enable_ct(c_ctx, SSL_CT_VALIDATION_STRICT)) {
Packit c4476c
        ERR_print_errors(bio_err);
Packit c4476c
        goto end;
Packit c4476c
    }
Packit c4476c
#endif
Packit c4476c
Packit c4476c
    /* Process SSL_CONF arguments */
Packit c4476c
    SSL_CONF_CTX_set_ssl_ctx(c_cctx, c_ctx);
Packit c4476c
    SSL_CONF_CTX_set_ssl_ctx(s_cctx, s_ctx);
Packit c4476c
    SSL_CONF_CTX_set_ssl_ctx(s_cctx2, s_ctx2);
Packit c4476c
Packit c4476c
    for (i = 0; i < sk_OPENSSL_STRING_num(conf_args); i += 2) {
Packit c4476c
        int rv;
Packit c4476c
        arg = sk_OPENSSL_STRING_value(conf_args, i);
Packit c4476c
        argn = sk_OPENSSL_STRING_value(conf_args, i + 1);
Packit c4476c
        rv = SSL_CONF_cmd(c_cctx, arg, argn);
Packit c4476c
        /* If not recognised use server context */
Packit c4476c
        if (rv == -2) {
Packit c4476c
            rv = SSL_CONF_cmd(s_cctx2, arg, argn);
Packit c4476c
            if (rv > 0)
Packit c4476c
                rv = SSL_CONF_cmd(s_cctx, arg, argn);
Packit c4476c
        }
Packit c4476c
        if (rv <= 0) {
Packit c4476c
            BIO_printf(bio_err, "Error processing %s %s\n",
Packit c4476c
                       arg, argn ? argn : "");
Packit c4476c
            ERR_print_errors(bio_err);
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (!SSL_CONF_CTX_finish(s_cctx) || !SSL_CONF_CTX_finish(c_cctx) || !SSL_CONF_CTX_finish(s_cctx2)) {
Packit c4476c
        BIO_puts(bio_err, "Error finishing context\n");
Packit c4476c
        ERR_print_errors(bio_err);
Packit c4476c
        goto end;
Packit c4476c
    }
Packit c4476c
#ifndef OPENSSL_NO_DH
Packit c4476c
    if (!no_dhe) {
Packit c4476c
        if (dhe1024dsa) {
Packit c4476c
            dh = get_dh1024dsa();
Packit c4476c
        } else if (dhe512)
Packit c4476c
            dh = get_dh512();
Packit c4476c
        else
Packit c4476c
            dh = get_dh1024();
Packit c4476c
        SSL_CTX_set_tmp_dh(s_ctx, dh);
Packit c4476c
        SSL_CTX_set_tmp_dh(s_ctx2, dh);
Packit c4476c
        DH_free(dh);
Packit c4476c
    }
Packit c4476c
#else
Packit c4476c
    (void)no_dhe;
Packit c4476c
#endif
Packit c4476c
Packit c4476c
    if ((!SSL_CTX_load_verify_locations(s_ctx, CAfile, CApath)) ||
Packit c4476c
        (!SSL_CTX_set_default_verify_paths(s_ctx)) ||
Packit c4476c
        (!SSL_CTX_load_verify_locations(s_ctx2, CAfile, CApath)) ||
Packit c4476c
        (!SSL_CTX_set_default_verify_paths(s_ctx2)) ||
Packit c4476c
        (!SSL_CTX_load_verify_locations(c_ctx, CAfile, CApath)) ||
Packit c4476c
        (!SSL_CTX_set_default_verify_paths(c_ctx))) {
Packit c4476c
        ERR_print_errors(bio_err);
Packit c4476c
    }
Packit c4476c
Packit c4476c
#ifndef OPENSSL_NO_CT
Packit c4476c
    if (!SSL_CTX_set_default_ctlog_list_file(s_ctx) ||
Packit c4476c
        !SSL_CTX_set_default_ctlog_list_file(s_ctx2) ||
Packit c4476c
        !SSL_CTX_set_default_ctlog_list_file(c_ctx)) {
Packit c4476c
        ERR_print_errors(bio_err);
Packit c4476c
    }
Packit c4476c
#endif
Packit c4476c
Packit c4476c
    if (client_auth) {
Packit c4476c
        printf("client authentication\n");
Packit c4476c
        SSL_CTX_set_verify(s_ctx,
Packit c4476c
                           SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
Packit c4476c
                           verify_callback);
Packit c4476c
        SSL_CTX_set_verify(s_ctx2,
Packit c4476c
                           SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
Packit c4476c
                           verify_callback);
Packit c4476c
        SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback,
Packit c4476c
                                         &app_verify_arg);
Packit c4476c
        SSL_CTX_set_cert_verify_callback(s_ctx2, app_verify_callback,
Packit c4476c
                                         &app_verify_arg);
Packit c4476c
    }
Packit c4476c
    if (server_auth) {
Packit c4476c
        printf("server authentication\n");
Packit c4476c
        SSL_CTX_set_verify(c_ctx, SSL_VERIFY_PEER, verify_callback);
Packit c4476c
        SSL_CTX_set_cert_verify_callback(c_ctx, app_verify_callback,
Packit c4476c
                                         &app_verify_arg);
Packit c4476c
    }
Packit c4476c
Packit c4476c
    {
Packit c4476c
        int session_id_context = 0;
Packit c4476c
        if (!SSL_CTX_set_session_id_context(s_ctx, (void *)&session_id_context,
Packit c4476c
                                            sizeof(session_id_context)) ||
Packit c4476c
            !SSL_CTX_set_session_id_context(s_ctx2, (void *)&session_id_context,
Packit c4476c
                                            sizeof(session_id_context))) {
Packit c4476c
            ERR_print_errors(bio_err);
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
Packit c4476c
    /* Use PSK only if PSK key is given */
Packit c4476c
    if (psk_key != NULL) {
Packit c4476c
        /*
Packit c4476c
         * no_psk is used to avoid putting psk command to openssl tool
Packit c4476c
         */
Packit c4476c
        if (no_psk) {
Packit c4476c
            /*
Packit c4476c
             * if PSK is not compiled in and psk key is given, do nothing and
Packit c4476c
             * exit successfully
Packit c4476c
             */
Packit c4476c
            ret = EXIT_SUCCESS;
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
#ifndef OPENSSL_NO_PSK
Packit c4476c
        SSL_CTX_set_psk_client_callback(c_ctx, psk_client_callback);
Packit c4476c
        SSL_CTX_set_psk_server_callback(s_ctx, psk_server_callback);
Packit c4476c
        SSL_CTX_set_psk_server_callback(s_ctx2, psk_server_callback);
Packit c4476c
        if (debug)
Packit c4476c
            BIO_printf(bio_err, "setting PSK identity hint to s_ctx\n");
Packit c4476c
        if (!SSL_CTX_use_psk_identity_hint(s_ctx, "ctx server identity_hint") ||
Packit c4476c
            !SSL_CTX_use_psk_identity_hint(s_ctx2, "ctx server identity_hint")) {
Packit c4476c
            BIO_printf(bio_err, "error setting PSK identity hint to s_ctx\n");
Packit c4476c
            ERR_print_errors(bio_err);
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
#endif
Packit c4476c
    }
Packit c4476c
Packit c4476c
#ifndef OPENSSL_NO_NEXTPROTONEG
Packit c4476c
    if (npn_client) {
Packit c4476c
        SSL_CTX_set_next_proto_select_cb(c_ctx, cb_client_npn, NULL);
Packit c4476c
    }
Packit c4476c
    if (npn_server) {
Packit c4476c
        if (npn_server_reject) {
Packit c4476c
            BIO_printf(bio_err,
Packit c4476c
                       "Can't have both -npn_server and -npn_server_reject\n");
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
        SSL_CTX_set_npn_advertised_cb(s_ctx, cb_server_npn, NULL);
Packit c4476c
        SSL_CTX_set_npn_advertised_cb(s_ctx2, cb_server_npn, NULL);
Packit c4476c
    }
Packit c4476c
    if (npn_server_reject) {
Packit c4476c
        SSL_CTX_set_npn_advertised_cb(s_ctx, cb_server_rejects_npn, NULL);
Packit c4476c
        SSL_CTX_set_npn_advertised_cb(s_ctx2, cb_server_rejects_npn, NULL);
Packit c4476c
    }
Packit c4476c
#endif
Packit c4476c
Packit c4476c
    if (serverinfo_sct) {
Packit c4476c
        if (!SSL_CTX_add_client_custom_ext(c_ctx,
Packit c4476c
                TLSEXT_TYPE_signed_certificate_timestamp,
Packit c4476c
                NULL, NULL, NULL,
Packit c4476c
                serverinfo_cli_parse_cb, NULL)) {
Packit c4476c
            BIO_printf(bio_err, "Error adding SCT extension\n");
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
    if (serverinfo_tack) {
Packit c4476c
        if (!SSL_CTX_add_client_custom_ext(c_ctx, TACK_EXT_TYPE,
Packit c4476c
                                      NULL, NULL, NULL,
Packit c4476c
                                      serverinfo_cli_parse_cb, NULL)) {
Packit c4476c
            BIO_printf(bio_err, "Error adding TACK extension\n");
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
    if (serverinfo_file)
Packit c4476c
        if (!SSL_CTX_use_serverinfo_file(s_ctx, serverinfo_file) ||
Packit c4476c
            !SSL_CTX_use_serverinfo_file(s_ctx2, serverinfo_file)) {
Packit c4476c
            BIO_printf(bio_err, "missing serverinfo file\n");
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
Packit c4476c
    if (custom_ext) {
Packit c4476c
        if (!SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_0,
Packit c4476c
                                      custom_ext_0_cli_add_cb,
Packit c4476c
                                      NULL, NULL,
Packit c4476c
                                      custom_ext_0_cli_parse_cb, NULL)
Packit c4476c
            || !SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_1,
Packit c4476c
                                      custom_ext_1_cli_add_cb,
Packit c4476c
                                      NULL, NULL,
Packit c4476c
                                      custom_ext_1_cli_parse_cb, NULL)
Packit c4476c
            || !SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_2,
Packit c4476c
                                      custom_ext_2_cli_add_cb,
Packit c4476c
                                      NULL, NULL,
Packit c4476c
                                      custom_ext_2_cli_parse_cb, NULL)
Packit c4476c
            || !SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_3,
Packit c4476c
                                      custom_ext_3_cli_add_cb,
Packit c4476c
                                      NULL, NULL,
Packit c4476c
                                      custom_ext_3_cli_parse_cb, NULL)
Packit c4476c
            || !SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_0,
Packit c4476c
                                      custom_ext_0_srv_add_cb,
Packit c4476c
                                      NULL, NULL,
Packit c4476c
                                      custom_ext_0_srv_parse_cb, NULL)
Packit c4476c
            || !SSL_CTX_add_server_custom_ext(s_ctx2, CUSTOM_EXT_TYPE_0,
Packit c4476c
                                      custom_ext_0_srv_add_cb,
Packit c4476c
                                      NULL, NULL,
Packit c4476c
                                      custom_ext_0_srv_parse_cb, NULL)
Packit c4476c
            || !SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_1,
Packit c4476c
                                      custom_ext_1_srv_add_cb,
Packit c4476c
                                      NULL, NULL,
Packit c4476c
                                      custom_ext_1_srv_parse_cb, NULL)
Packit c4476c
            || !SSL_CTX_add_server_custom_ext(s_ctx2, CUSTOM_EXT_TYPE_1,
Packit c4476c
                                      custom_ext_1_srv_add_cb,
Packit c4476c
                                      NULL, NULL,
Packit c4476c
                                      custom_ext_1_srv_parse_cb, NULL)
Packit c4476c
            || !SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_2,
Packit c4476c
                                      custom_ext_2_srv_add_cb,
Packit c4476c
                                      NULL, NULL,
Packit c4476c
                                      custom_ext_2_srv_parse_cb, NULL)
Packit c4476c
            || !SSL_CTX_add_server_custom_ext(s_ctx2, CUSTOM_EXT_TYPE_2,
Packit c4476c
                                      custom_ext_2_srv_add_cb,
Packit c4476c
                                      NULL, NULL,
Packit c4476c
                                      custom_ext_2_srv_parse_cb, NULL)
Packit c4476c
            || !SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_3,
Packit c4476c
                                      custom_ext_3_srv_add_cb,
Packit c4476c
                                      NULL, NULL,
Packit c4476c
                                      custom_ext_3_srv_parse_cb, NULL)
Packit c4476c
            || !SSL_CTX_add_server_custom_ext(s_ctx2, CUSTOM_EXT_TYPE_3,
Packit c4476c
                                      custom_ext_3_srv_add_cb,
Packit c4476c
                                      NULL, NULL,
Packit c4476c
                                      custom_ext_3_srv_parse_cb, NULL)) {
Packit c4476c
            BIO_printf(bio_err, "Error setting custom extensions\n");
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (alpn_server)
Packit c4476c
        SSL_CTX_set_alpn_select_cb(s_ctx, cb_server_alpn, alpn_server);
Packit c4476c
    if (alpn_server2)
Packit c4476c
        SSL_CTX_set_alpn_select_cb(s_ctx2, cb_server_alpn, alpn_server2);
Packit c4476c
Packit c4476c
    if (alpn_client) {
Packit c4476c
        size_t alpn_len;
Packit c4476c
        unsigned char *alpn = next_protos_parse(&alpn_len, alpn_client);
Packit c4476c
Packit c4476c
        if (alpn == NULL) {
Packit c4476c
            BIO_printf(bio_err, "Error parsing -alpn_client argument\n");
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
        /* Returns 0 on success!! */
Packit c4476c
        if (SSL_CTX_set_alpn_protos(c_ctx, alpn, alpn_len)) {
Packit c4476c
            BIO_printf(bio_err, "Error setting ALPN\n");
Packit c4476c
            OPENSSL_free(alpn);
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
        OPENSSL_free(alpn);
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (server_sess_in != NULL) {
Packit c4476c
        server_sess = read_session(server_sess_in);
Packit c4476c
        if (server_sess == NULL)
Packit c4476c
            goto end;
Packit c4476c
    }
Packit c4476c
    if (client_sess_in != NULL) {
Packit c4476c
        client_sess = read_session(client_sess_in);
Packit c4476c
        if (client_sess == NULL)
Packit c4476c
            goto end;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (server_sess_out != NULL || server_sess_in != NULL) {
Packit c4476c
        char *keys;
Packit c4476c
        long size;
Packit c4476c
Packit c4476c
        /* Use a fixed key so that we can decrypt the ticket. */
Packit c4476c
        size = SSL_CTX_set_tlsext_ticket_keys(s_ctx, NULL, 0);
Packit c4476c
        keys = OPENSSL_zalloc(size);
Packit c4476c
        SSL_CTX_set_tlsext_ticket_keys(s_ctx, keys, size);
Packit c4476c
        OPENSSL_free(keys);
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (sn_server1 != NULL || sn_server2 != NULL)
Packit c4476c
        SSL_CTX_set_tlsext_servername_callback(s_ctx, servername_cb);
Packit c4476c
Packit c4476c
    c_ssl = SSL_new(c_ctx);
Packit c4476c
    s_ssl = SSL_new(s_ctx);
Packit c4476c
Packit c4476c
    if (sn_client)
Packit c4476c
        SSL_set_tlsext_host_name(c_ssl, sn_client);
Packit c4476c
Packit c4476c
    if (!set_protocol_version(server_min_proto, s_ssl, SSL_CTRL_SET_MIN_PROTO_VERSION))
Packit c4476c
        goto end;
Packit c4476c
    if (!set_protocol_version(server_max_proto, s_ssl, SSL_CTRL_SET_MAX_PROTO_VERSION))
Packit c4476c
        goto end;
Packit c4476c
    if (!set_protocol_version(client_min_proto, c_ssl, SSL_CTRL_SET_MIN_PROTO_VERSION))
Packit c4476c
        goto end;
Packit c4476c
    if (!set_protocol_version(client_max_proto, c_ssl, SSL_CTRL_SET_MAX_PROTO_VERSION))
Packit c4476c
        goto end;
Packit c4476c
Packit c4476c
    if (server_sess) {
Packit c4476c
        if (SSL_CTX_add_session(s_ctx, server_sess) == 0) {
Packit c4476c
            BIO_printf(bio_err, "Can't add server session\n");
Packit c4476c
            ERR_print_errors(bio_err);
Packit c4476c
            goto end;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
Packit c4476c
    BIO_printf(bio_stdout, "Doing handshakes=%d bytes=%ld\n", number, bytes);
Packit c4476c
    for (i = 0; i < number; i++) {
Packit c4476c
        if (!reuse) {
Packit c4476c
            if (!SSL_set_session(c_ssl, NULL)) {
Packit c4476c
                BIO_printf(bio_err, "Failed to set session\n");
Packit c4476c
                goto end;
Packit c4476c
            }
Packit c4476c
        }
Packit c4476c
        if (client_sess_in != NULL) {
Packit c4476c
            if (SSL_set_session(c_ssl, client_sess) == 0) {
Packit c4476c
                BIO_printf(bio_err, "Can't set client session\n");
Packit c4476c
                ERR_print_errors(bio_err);
Packit c4476c
                goto end;
Packit c4476c
            }
Packit c4476c
        }
Packit c4476c
        switch (bio_type) {
Packit c4476c
        case BIO_MEM:
Packit c4476c
            ret = doit(s_ssl, c_ssl, bytes);
Packit c4476c
            break;
Packit c4476c
        case BIO_PAIR:
Packit c4476c
            ret = doit_biopair(s_ssl, c_ssl, bytes, &s_time, &c_time);
Packit c4476c
            break;
Packit c4476c
#ifndef OPENSSL_NO_SOCK
Packit c4476c
        case BIO_IPV4:
Packit c4476c
            ret = doit_localhost(s_ssl, c_ssl, BIO_FAMILY_IPV4,
Packit c4476c
                                 bytes, &s_time, &c_time);
Packit c4476c
            break;
Packit c4476c
        case BIO_IPV6:
Packit c4476c
            ret = doit_localhost(s_ssl, c_ssl, BIO_FAMILY_IPV6,
Packit c4476c
                                 bytes, &s_time, &c_time);
Packit c4476c
            break;
Packit c4476c
#else
Packit c4476c
        case BIO_IPV4:
Packit c4476c
        case BIO_IPV6:
Packit c4476c
            ret = EXIT_FAILURE;
Packit c4476c
            goto err;
Packit c4476c
#endif
Packit c4476c
        }
Packit c4476c
        if (ret != EXIT_SUCCESS)  break;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (should_negotiate && ret == EXIT_SUCCESS &&
Packit c4476c
        strcmp(should_negotiate, "fail-server") != 0 &&
Packit c4476c
        strcmp(should_negotiate, "fail-client") != 0) {
Packit c4476c
        int version = protocol_from_string(should_negotiate);
Packit c4476c
        if (version < 0) {
Packit c4476c
            BIO_printf(bio_err, "Error parsing: %s\n", should_negotiate);
Packit c4476c
            ret = EXIT_FAILURE;
Packit c4476c
            goto err;
Packit c4476c
        }
Packit c4476c
        if (SSL_version(c_ssl) != version) {
Packit c4476c
            BIO_printf(bio_err, "Unexpected version negotiated. "
Packit c4476c
                "Expected: %s, got %s\n", should_negotiate, SSL_get_version(c_ssl));
Packit c4476c
            ret = EXIT_FAILURE;
Packit c4476c
            goto err;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (should_reuse != -1) {
Packit c4476c
        if (SSL_session_reused(s_ssl) != should_reuse ||
Packit c4476c
            SSL_session_reused(c_ssl) != should_reuse) {
Packit c4476c
            BIO_printf(bio_err, "Unexpected session reuse state. "
Packit c4476c
                "Expected: %d, server: %d, client: %d\n", should_reuse,
Packit c4476c
                SSL_session_reused(s_ssl), SSL_session_reused(c_ssl));
Packit c4476c
            ret = EXIT_FAILURE;
Packit c4476c
            goto err;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (server_sess_out != NULL) {
Packit c4476c
        if (write_session(server_sess_out, SSL_get_session(s_ssl)) == 0) {
Packit c4476c
            ret = EXIT_FAILURE;
Packit c4476c
            goto err;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
    if (client_sess_out != NULL) {
Packit c4476c
        if (write_session(client_sess_out, SSL_get_session(c_ssl)) == 0) {
Packit c4476c
            ret = EXIT_FAILURE;
Packit c4476c
            goto err;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (!verbose) {
Packit c4476c
        print_details(c_ssl, "");
Packit c4476c
    }
Packit c4476c
    if (print_time) {
Packit c4476c
#ifdef CLOCKS_PER_SEC
Packit c4476c
        /*
Packit c4476c
         * "To determine the time in seconds, the value returned by the clock
Packit c4476c
         * function should be divided by the value of the macro
Packit c4476c
         * CLOCKS_PER_SEC." -- ISO/IEC 9899
Packit c4476c
         */
Packit c4476c
        BIO_printf(bio_stdout, "Approximate total server time: %6.2f s\n"
Packit c4476c
                   "Approximate total client time: %6.2f s\n",
Packit c4476c
                   (double)s_time / CLOCKS_PER_SEC,
Packit c4476c
                   (double)c_time / CLOCKS_PER_SEC);
Packit c4476c
#else
Packit c4476c
        BIO_printf(bio_stdout,
Packit c4476c
                   "Approximate total server time: %6.2f units\n"
Packit c4476c
                   "Approximate total client time: %6.2f units\n",
Packit c4476c
                   (double)s_time, (double)c_time);
Packit c4476c
#endif
Packit c4476c
    }
Packit c4476c
Packit c4476c
 err:
Packit c4476c
    SSL_free(s_ssl);
Packit c4476c
    SSL_free(c_ssl);
Packit c4476c
Packit c4476c
 end:
Packit c4476c
    SSL_CTX_free(s_ctx);
Packit c4476c
    SSL_CTX_free(s_ctx2);
Packit c4476c
    SSL_CTX_free(c_ctx);
Packit c4476c
    SSL_CONF_CTX_free(s_cctx);
Packit c4476c
    SSL_CONF_CTX_free(s_cctx2);
Packit c4476c
    SSL_CONF_CTX_free(c_cctx);
Packit c4476c
    sk_OPENSSL_STRING_free(conf_args);
Packit c4476c
Packit c4476c
    BIO_free(bio_stdout);
Packit c4476c
Packit c4476c
    SSL_SESSION_free(server_sess);
Packit c4476c
    SSL_SESSION_free(client_sess);
Packit c4476c
Packit c4476c
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
Packit c4476c
    if (CRYPTO_mem_leaks(bio_err) <= 0)
Packit c4476c
        ret = EXIT_FAILURE;
Packit c4476c
#endif
Packit c4476c
    BIO_free(bio_err);
Packit c4476c
    EXIT(ret);
Packit c4476c
}
Packit c4476c
Packit c4476c
#ifndef OPENSSL_NO_SOCK
Packit c4476c
int doit_localhost(SSL *s_ssl, SSL *c_ssl, int family, long count,
Packit c4476c
                   clock_t *s_time, clock_t *c_time)
Packit c4476c
{
Packit c4476c
    long cw_num = count, cr_num = count, sw_num = count, sr_num = count;
Packit c4476c
    BIO *s_ssl_bio = NULL, *c_ssl_bio = NULL;
Packit c4476c
    BIO *acpt = NULL, *server = NULL, *client = NULL;
Packit c4476c
    char addr_str[40];
Packit c4476c
    int ret = EXIT_FAILURE;
Packit c4476c
    int err_in_client = 0;
Packit c4476c
    int err_in_server = 0;
Packit c4476c
Packit c4476c
    acpt = BIO_new_accept(family == BIO_FAMILY_IPV4 ? "127.0.0.1:0"
Packit c4476c
                                                    : "[::1]:0");
Packit c4476c
    if (acpt == NULL)
Packit c4476c
        goto err;
Packit c4476c
    BIO_set_accept_ip_family(acpt, family);
Packit c4476c
    BIO_set_bind_mode(acpt, BIO_SOCK_NONBLOCK | BIO_SOCK_REUSEADDR);
Packit c4476c
    if (BIO_do_accept(acpt) <= 0)
Packit c4476c
        goto err;
Packit c4476c
Packit c4476c
    BIO_snprintf(addr_str, sizeof(addr_str), ":%s", BIO_get_accept_port(acpt));
Packit c4476c
Packit c4476c
    client = BIO_new_connect(addr_str);
Packit c4476c
    BIO_set_conn_ip_family(client, family);
Packit c4476c
    if (!client)
Packit c4476c
        goto err;
Packit c4476c
Packit c4476c
    if (BIO_set_nbio(client, 1) <= 0)
Packit c4476c
        goto err;
Packit c4476c
    if (BIO_set_nbio(acpt, 1) <= 0)
Packit c4476c
        goto err;
Packit c4476c
Packit c4476c
    {
Packit c4476c
        int st_connect = 0, st_accept = 0;
Packit c4476c
Packit c4476c
        while(!st_connect || !st_accept) {
Packit c4476c
            if (!st_connect) {
Packit c4476c
                if (BIO_do_connect(client) <= 0) {
Packit c4476c
                    if (!BIO_should_retry(client))
Packit c4476c
                        goto err;
Packit c4476c
                } else {
Packit c4476c
                    st_connect = 1;
Packit c4476c
                }
Packit c4476c
            }
Packit c4476c
            if (!st_accept) {
Packit c4476c
                if (BIO_do_accept(acpt) <= 0) {
Packit c4476c
                    if (!BIO_should_retry(acpt))
Packit c4476c
                        goto err;
Packit c4476c
                } else {
Packit c4476c
                    st_accept = 1;
Packit c4476c
                }
Packit c4476c
            }
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
    /* We're not interested in accepting further connects */
Packit c4476c
    server = BIO_pop(acpt);
Packit c4476c
    BIO_free_all(acpt);
Packit c4476c
    acpt = NULL;
Packit c4476c
Packit c4476c
    s_ssl_bio = BIO_new(BIO_f_ssl());
Packit c4476c
    if (!s_ssl_bio)
Packit c4476c
        goto err;
Packit c4476c
Packit c4476c
    c_ssl_bio = BIO_new(BIO_f_ssl());
Packit c4476c
    if (!c_ssl_bio)
Packit c4476c
        goto err;
Packit c4476c
Packit c4476c
    SSL_set_connect_state(c_ssl);
Packit c4476c
    SSL_set_bio(c_ssl, client, client);
Packit c4476c
    (void)BIO_set_ssl(c_ssl_bio, c_ssl, BIO_NOCLOSE);
Packit c4476c
Packit c4476c
    SSL_set_accept_state(s_ssl);
Packit c4476c
    SSL_set_bio(s_ssl, server, server);
Packit c4476c
    (void)BIO_set_ssl(s_ssl_bio, s_ssl, BIO_NOCLOSE);
Packit c4476c
Packit c4476c
    do {
Packit c4476c
        /*-
Packit c4476c
         * c_ssl_bio:          SSL filter BIO
Packit c4476c
         *
Packit c4476c
         * client:             I/O for SSL library
Packit c4476c
         *
Packit c4476c
         *
Packit c4476c
         * server:             I/O for SSL library
Packit c4476c
         *
Packit c4476c
         * s_ssl_bio:          SSL filter BIO
Packit c4476c
         */
Packit c4476c
Packit c4476c
        /*
Packit c4476c
         * We have non-blocking behaviour throughout this test program, but
Packit c4476c
         * can be sure that there is *some* progress in each iteration; so we
Packit c4476c
         * don't have to worry about ..._SHOULD_READ or ..._SHOULD_WRITE --
Packit c4476c
         * we just try everything in each iteration
Packit c4476c
         */
Packit c4476c
Packit c4476c
        {
Packit c4476c
            /* CLIENT */
Packit c4476c
Packit c4476c
            char cbuf[1024 * 8];
Packit c4476c
            int i, r;
Packit c4476c
            clock_t c_clock = clock();
Packit c4476c
Packit c4476c
            memset(cbuf, 0, sizeof(cbuf));
Packit c4476c
Packit c4476c
            if (debug)
Packit c4476c
                if (SSL_in_init(c_ssl))
Packit c4476c
                    printf("client waiting in SSL_connect - %s\n",
Packit c4476c
                           SSL_state_string_long(c_ssl));
Packit c4476c
Packit c4476c
            if (cw_num > 0) {
Packit c4476c
                /* Write to server. */
Packit c4476c
Packit c4476c
                if (cw_num > (long)sizeof(cbuf))
Packit c4476c
                    i = sizeof(cbuf);
Packit c4476c
                else
Packit c4476c
                    i = (int)cw_num;
Packit c4476c
                r = BIO_write(c_ssl_bio, cbuf, i);
Packit c4476c
                if (r < 0) {
Packit c4476c
                    if (!BIO_should_retry(c_ssl_bio)) {
Packit c4476c
                        fprintf(stderr, "ERROR in CLIENT\n");
Packit c4476c
                        err_in_client = 1;
Packit c4476c
                        goto err;
Packit c4476c
                    }
Packit c4476c
                    /*
Packit c4476c
                     * BIO_should_retry(...) can just be ignored here. The
Packit c4476c
                     * library expects us to call BIO_write with the same
Packit c4476c
                     * arguments again, and that's what we will do in the
Packit c4476c
                     * next iteration.
Packit c4476c
                     */
Packit c4476c
                } else if (r == 0) {
Packit c4476c
                    fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
Packit c4476c
                    goto err;
Packit c4476c
                } else {
Packit c4476c
                    if (debug)
Packit c4476c
                        printf("client wrote %d\n", r);
Packit c4476c
                    cw_num -= r;
Packit c4476c
                }
Packit c4476c
            }
Packit c4476c
Packit c4476c
            if (cr_num > 0) {
Packit c4476c
                /* Read from server. */
Packit c4476c
Packit c4476c
                r = BIO_read(c_ssl_bio, cbuf, sizeof(cbuf));
Packit c4476c
                if (r < 0) {
Packit c4476c
                    if (!BIO_should_retry(c_ssl_bio)) {
Packit c4476c
                        fprintf(stderr, "ERROR in CLIENT\n");
Packit c4476c
                        err_in_client = 1;
Packit c4476c
                        goto err;
Packit c4476c
                    }
Packit c4476c
                    /*
Packit c4476c
                     * Again, "BIO_should_retry" can be ignored.
Packit c4476c
                     */
Packit c4476c
                } else if (r == 0) {
Packit c4476c
                    fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
Packit c4476c
                    goto err;
Packit c4476c
                } else {
Packit c4476c
                    if (debug)
Packit c4476c
                        printf("client read %d\n", r);
Packit c4476c
                    cr_num -= r;
Packit c4476c
                }
Packit c4476c
            }
Packit c4476c
Packit c4476c
            /*
Packit c4476c
             * c_time and s_time increments will typically be very small
Packit c4476c
             * (depending on machine speed and clock tick intervals), but
Packit c4476c
             * sampling over a large number of connections should result in
Packit c4476c
             * fairly accurate figures.  We cannot guarantee a lot, however
Packit c4476c
             * -- if each connection lasts for exactly one clock tick, it
Packit c4476c
             * will be counted only for the client or only for the server or
Packit c4476c
             * even not at all.
Packit c4476c
             */
Packit c4476c
            *c_time += (clock() - c_clock);
Packit c4476c
        }
Packit c4476c
Packit c4476c
        {
Packit c4476c
            /* SERVER */
Packit c4476c
Packit c4476c
            char sbuf[1024 * 8];
Packit c4476c
            int i, r;
Packit c4476c
            clock_t s_clock = clock();
Packit c4476c
Packit c4476c
            memset(sbuf, 0, sizeof(sbuf));
Packit c4476c
Packit c4476c
            if (debug)
Packit c4476c
                if (SSL_in_init(s_ssl))
Packit c4476c
                    printf("server waiting in SSL_accept - %s\n",
Packit c4476c
                           SSL_state_string_long(s_ssl));
Packit c4476c
Packit c4476c
            if (sw_num > 0) {
Packit c4476c
                /* Write to client. */
Packit c4476c
Packit c4476c
                if (sw_num > (long)sizeof(sbuf))
Packit c4476c
                    i = sizeof(sbuf);
Packit c4476c
                else
Packit c4476c
                    i = (int)sw_num;
Packit c4476c
                r = BIO_write(s_ssl_bio, sbuf, i);
Packit c4476c
                if (r < 0) {
Packit c4476c
                    if (!BIO_should_retry(s_ssl_bio)) {
Packit c4476c
                        fprintf(stderr, "ERROR in SERVER\n");
Packit c4476c
                        err_in_server = 1;
Packit c4476c
                        goto err;
Packit c4476c
                    }
Packit c4476c
                    /* Ignore "BIO_should_retry". */
Packit c4476c
                } else if (r == 0) {
Packit c4476c
                    fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
Packit c4476c
                    goto err;
Packit c4476c
                } else {
Packit c4476c
                    if (debug)
Packit c4476c
                        printf("server wrote %d\n", r);
Packit c4476c
                    sw_num -= r;
Packit c4476c
                }
Packit c4476c
            }
Packit c4476c
Packit c4476c
            if (sr_num > 0) {
Packit c4476c
                /* Read from client. */
Packit c4476c
Packit c4476c
                r = BIO_read(s_ssl_bio, sbuf, sizeof(sbuf));
Packit c4476c
                if (r < 0) {
Packit c4476c
                    if (!BIO_should_retry(s_ssl_bio)) {
Packit c4476c
                        fprintf(stderr, "ERROR in SERVER\n");
Packit c4476c
                        err_in_server = 1;
Packit c4476c
                        goto err;
Packit c4476c
                    }
Packit c4476c
                    /* blah, blah */
Packit c4476c
                } else if (r == 0) {
Packit c4476c
                    fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
Packit c4476c
                    goto err;
Packit c4476c
                } else {
Packit c4476c
                    if (debug)
Packit c4476c
                        printf("server read %d\n", r);
Packit c4476c
                    sr_num -= r;
Packit c4476c
                }
Packit c4476c
            }
Packit c4476c
Packit c4476c
            *s_time += (clock() - s_clock);
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
    while (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0);
Packit c4476c
Packit c4476c
    if (verbose)
Packit c4476c
        print_details(c_ssl, "DONE via TCP connect: ");
Packit c4476c
# ifndef OPENSSL_NO_NEXTPROTONEG
Packit c4476c
    if (verify_npn(c_ssl, s_ssl) < 0)
Packit c4476c
        goto end;
Packit c4476c
# endif
Packit c4476c
    if (verify_serverinfo() < 0) {
Packit c4476c
        fprintf(stderr, "Server info verify error\n");
Packit c4476c
        goto err;
Packit c4476c
    }
Packit c4476c
    if (verify_alpn(c_ssl, s_ssl) < 0
Packit c4476c
            || verify_servername(c_ssl, s_ssl) < 0)
Packit c4476c
        goto err;
Packit c4476c
Packit c4476c
    if (custom_ext_error) {
Packit c4476c
        fprintf(stderr, "Custom extension error\n");
Packit c4476c
        goto err;
Packit c4476c
    }
Packit c4476c
Packit c4476c
# ifndef OPENSSL_NO_NEXTPROTONEG
Packit c4476c
 end:
Packit c4476c
# endif
Packit c4476c
    ret = EXIT_SUCCESS;
Packit c4476c
Packit c4476c
 err:
Packit c4476c
    ERR_print_errors(bio_err);
Packit c4476c
Packit c4476c
    BIO_free_all(acpt);
Packit c4476c
    BIO_free(server);
Packit c4476c
    BIO_free(client);
Packit c4476c
    BIO_free(s_ssl_bio);
Packit c4476c
    BIO_free(c_ssl_bio);
Packit c4476c
Packit c4476c
    if (should_negotiate != NULL && strcmp(should_negotiate, "fail-client") == 0)
Packit c4476c
        ret = (err_in_client != 0) ? EXIT_SUCCESS : EXIT_FAILURE;
Packit c4476c
    else if (should_negotiate != NULL && strcmp(should_negotiate, "fail-server") == 0)
Packit c4476c
        ret = (err_in_server != 0) ? EXIT_SUCCESS : EXIT_FAILURE;
Packit c4476c
Packit c4476c
    return ret;
Packit c4476c
}
Packit c4476c
#endif
Packit c4476c
Packit c4476c
int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count,
Packit c4476c
                 clock_t *s_time, clock_t *c_time)
Packit c4476c
{
Packit c4476c
    long cw_num = count, cr_num = count, sw_num = count, sr_num = count;
Packit c4476c
    BIO *s_ssl_bio = NULL, *c_ssl_bio = NULL;
Packit c4476c
    BIO *server = NULL, *server_io = NULL, *client = NULL, *client_io = NULL;
Packit c4476c
    int ret = EXIT_FAILURE;
Packit c4476c
    int err_in_client = 0;
Packit c4476c
    int err_in_server = 0;
Packit c4476c
Packit c4476c
    size_t bufsiz = 256;        /* small buffer for testing */
Packit c4476c
Packit c4476c
    if (!BIO_new_bio_pair(&server, bufsiz, &server_io, bufsiz))
Packit c4476c
        goto err;
Packit c4476c
    if (!BIO_new_bio_pair(&client, bufsiz, &client_io, bufsiz))
Packit c4476c
        goto err;
Packit c4476c
Packit c4476c
    s_ssl_bio = BIO_new(BIO_f_ssl());
Packit c4476c
    if (!s_ssl_bio)
Packit c4476c
        goto err;
Packit c4476c
Packit c4476c
    c_ssl_bio = BIO_new(BIO_f_ssl());
Packit c4476c
    if (!c_ssl_bio)
Packit c4476c
        goto err;
Packit c4476c
Packit c4476c
    SSL_set_connect_state(c_ssl);
Packit c4476c
    SSL_set_bio(c_ssl, client, client);
Packit c4476c
    (void)BIO_set_ssl(c_ssl_bio, c_ssl, BIO_NOCLOSE);
Packit c4476c
Packit c4476c
    SSL_set_accept_state(s_ssl);
Packit c4476c
    SSL_set_bio(s_ssl, server, server);
Packit c4476c
    (void)BIO_set_ssl(s_ssl_bio, s_ssl, BIO_NOCLOSE);
Packit c4476c
Packit c4476c
    do {
Packit c4476c
        /*-
Packit c4476c
         * c_ssl_bio:          SSL filter BIO
Packit c4476c
         *
Packit c4476c
         * client:             pseudo-I/O for SSL library
Packit c4476c
         *
Packit c4476c
         * client_io:          client's SSL communication; usually to be
Packit c4476c
         *                     relayed over some I/O facility, but in this
Packit c4476c
         *                     test program, we're the server, too:
Packit c4476c
         *
Packit c4476c
         * server_io:          server's SSL communication
Packit c4476c
         *
Packit c4476c
         * server:             pseudo-I/O for SSL library
Packit c4476c
         *
Packit c4476c
         * s_ssl_bio:          SSL filter BIO
Packit c4476c
         *
Packit c4476c
         * The client and the server each employ a "BIO pair":
Packit c4476c
         * client + client_io, server + server_io.
Packit c4476c
         * BIO pairs are symmetric.  A BIO pair behaves similar
Packit c4476c
         * to a non-blocking socketpair (but both endpoints must
Packit c4476c
         * be handled by the same thread).
Packit c4476c
         * [Here we could connect client and server to the ends
Packit c4476c
         * of a single BIO pair, but then this code would be less
Packit c4476c
         * suitable as an example for BIO pairs in general.]
Packit c4476c
         *
Packit c4476c
         * Useful functions for querying the state of BIO pair endpoints:
Packit c4476c
         *
Packit c4476c
         * BIO_ctrl_pending(bio)              number of bytes we can read now
Packit c4476c
         * BIO_ctrl_get_read_request(bio)     number of bytes needed to fulfill
Packit c4476c
         *                                      other side's read attempt
Packit c4476c
         * BIO_ctrl_get_write_guarantee(bio)   number of bytes we can write now
Packit c4476c
         *
Packit c4476c
         * ..._read_request is never more than ..._write_guarantee;
Packit c4476c
         * it depends on the application which one you should use.
Packit c4476c
         */
Packit c4476c
Packit c4476c
        /*
Packit c4476c
         * We have non-blocking behaviour throughout this test program, but
Packit c4476c
         * can be sure that there is *some* progress in each iteration; so we
Packit c4476c
         * don't have to worry about ..._SHOULD_READ or ..._SHOULD_WRITE --
Packit c4476c
         * we just try everything in each iteration
Packit c4476c
         */
Packit c4476c
Packit c4476c
        {
Packit c4476c
            /* CLIENT */
Packit c4476c
Packit c4476c
            char cbuf[1024 * 8];
Packit c4476c
            int i, r;
Packit c4476c
            clock_t c_clock = clock();
Packit c4476c
Packit c4476c
            memset(cbuf, 0, sizeof(cbuf));
Packit c4476c
Packit c4476c
            if (debug)
Packit c4476c
                if (SSL_in_init(c_ssl))
Packit c4476c
                    printf("client waiting in SSL_connect - %s\n",
Packit c4476c
                           SSL_state_string_long(c_ssl));
Packit c4476c
Packit c4476c
            if (cw_num > 0) {
Packit c4476c
                /* Write to server. */
Packit c4476c
Packit c4476c
                if (cw_num > (long)sizeof(cbuf))
Packit c4476c
                    i = sizeof(cbuf);
Packit c4476c
                else
Packit c4476c
                    i = (int)cw_num;
Packit c4476c
                r = BIO_write(c_ssl_bio, cbuf, i);
Packit c4476c
                if (r < 0) {
Packit c4476c
                    if (!BIO_should_retry(c_ssl_bio)) {
Packit c4476c
                        fprintf(stderr, "ERROR in CLIENT\n");
Packit c4476c
                        err_in_client = 1;
Packit c4476c
                        goto err;
Packit c4476c
                    }
Packit c4476c
                    /*
Packit c4476c
                     * BIO_should_retry(...) can just be ignored here. The
Packit c4476c
                     * library expects us to call BIO_write with the same
Packit c4476c
                     * arguments again, and that's what we will do in the
Packit c4476c
                     * next iteration.
Packit c4476c
                     */
Packit c4476c
                } else if (r == 0) {
Packit c4476c
                    fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
Packit c4476c
                    goto err;
Packit c4476c
                } else {
Packit c4476c
                    if (debug)
Packit c4476c
                        printf("client wrote %d\n", r);
Packit c4476c
                    cw_num -= r;
Packit c4476c
                }
Packit c4476c
            }
Packit c4476c
Packit c4476c
            if (cr_num > 0) {
Packit c4476c
                /* Read from server. */
Packit c4476c
Packit c4476c
                r = BIO_read(c_ssl_bio, cbuf, sizeof(cbuf));
Packit c4476c
                if (r < 0) {
Packit c4476c
                    if (!BIO_should_retry(c_ssl_bio)) {
Packit c4476c
                        fprintf(stderr, "ERROR in CLIENT\n");
Packit c4476c
                        err_in_client = 1;
Packit c4476c
                        goto err;
Packit c4476c
                    }
Packit c4476c
                    /*
Packit c4476c
                     * Again, "BIO_should_retry" can be ignored.
Packit c4476c
                     */
Packit c4476c
                } else if (r == 0) {
Packit c4476c
                    fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
Packit c4476c
                    goto err;
Packit c4476c
                } else {
Packit c4476c
                    if (debug)
Packit c4476c
                        printf("client read %d\n", r);
Packit c4476c
                    cr_num -= r;
Packit c4476c
                }
Packit c4476c
            }
Packit c4476c
Packit c4476c
            /*
Packit c4476c
             * c_time and s_time increments will typically be very small
Packit c4476c
             * (depending on machine speed and clock tick intervals), but
Packit c4476c
             * sampling over a large number of connections should result in
Packit c4476c
             * fairly accurate figures.  We cannot guarantee a lot, however
Packit c4476c
             * -- if each connection lasts for exactly one clock tick, it
Packit c4476c
             * will be counted only for the client or only for the server or
Packit c4476c
             * even not at all.
Packit c4476c
             */
Packit c4476c
            *c_time += (clock() - c_clock);
Packit c4476c
        }
Packit c4476c
Packit c4476c
        {
Packit c4476c
            /* SERVER */
Packit c4476c
Packit c4476c
            char sbuf[1024 * 8];
Packit c4476c
            int i, r;
Packit c4476c
            clock_t s_clock = clock();
Packit c4476c
Packit c4476c
            memset(sbuf, 0, sizeof(sbuf));
Packit c4476c
Packit c4476c
            if (debug)
Packit c4476c
                if (SSL_in_init(s_ssl))
Packit c4476c
                    printf("server waiting in SSL_accept - %s\n",
Packit c4476c
                           SSL_state_string_long(s_ssl));
Packit c4476c
Packit c4476c
            if (sw_num > 0) {
Packit c4476c
                /* Write to client. */
Packit c4476c
Packit c4476c
                if (sw_num > (long)sizeof(sbuf))
Packit c4476c
                    i = sizeof(sbuf);
Packit c4476c
                else
Packit c4476c
                    i = (int)sw_num;
Packit c4476c
                r = BIO_write(s_ssl_bio, sbuf, i);
Packit c4476c
                if (r < 0) {
Packit c4476c
                    if (!BIO_should_retry(s_ssl_bio)) {
Packit c4476c
                        fprintf(stderr, "ERROR in SERVER\n");
Packit c4476c
                        err_in_server = 1;
Packit c4476c
                        goto err;
Packit c4476c
                    }
Packit c4476c
                    /* Ignore "BIO_should_retry". */
Packit c4476c
                } else if (r == 0) {
Packit c4476c
                    fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
Packit c4476c
                    goto err;
Packit c4476c
                } else {
Packit c4476c
                    if (debug)
Packit c4476c
                        printf("server wrote %d\n", r);
Packit c4476c
                    sw_num -= r;
Packit c4476c
                }
Packit c4476c
            }
Packit c4476c
Packit c4476c
            if (sr_num > 0) {
Packit c4476c
                /* Read from client. */
Packit c4476c
Packit c4476c
                r = BIO_read(s_ssl_bio, sbuf, sizeof(sbuf));
Packit c4476c
                if (r < 0) {
Packit c4476c
                    if (!BIO_should_retry(s_ssl_bio)) {
Packit c4476c
                        fprintf(stderr, "ERROR in SERVER\n");
Packit c4476c
                        err_in_server = 1;
Packit c4476c
                        goto err;
Packit c4476c
                    }
Packit c4476c
                    /* blah, blah */
Packit c4476c
                } else if (r == 0) {
Packit c4476c
                    fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
Packit c4476c
                    goto err;
Packit c4476c
                } else {
Packit c4476c
                    if (debug)
Packit c4476c
                        printf("server read %d\n", r);
Packit c4476c
                    sr_num -= r;
Packit c4476c
                }
Packit c4476c
            }
Packit c4476c
Packit c4476c
            *s_time += (clock() - s_clock);
Packit c4476c
        }
Packit c4476c
Packit c4476c
        {
Packit c4476c
            /* "I/O" BETWEEN CLIENT AND SERVER. */
Packit c4476c
Packit c4476c
            size_t r1, r2;
Packit c4476c
            BIO *io1 = server_io, *io2 = client_io;
Packit c4476c
            /*
Packit c4476c
             * we use the non-copying interface for io1 and the standard
Packit c4476c
             * BIO_write/BIO_read interface for io2
Packit c4476c
             */
Packit c4476c
Packit c4476c
            static int prev_progress = 1;
Packit c4476c
            int progress = 0;
Packit c4476c
Packit c4476c
            /* io1 to io2 */
Packit c4476c
            do {
Packit c4476c
                size_t num;
Packit c4476c
                int r;
Packit c4476c
Packit c4476c
                r1 = BIO_ctrl_pending(io1);
Packit c4476c
                r2 = BIO_ctrl_get_write_guarantee(io2);
Packit c4476c
Packit c4476c
                num = r1;
Packit c4476c
                if (r2 < num)
Packit c4476c
                    num = r2;
Packit c4476c
                if (num) {
Packit c4476c
                    char *dataptr;
Packit c4476c
Packit c4476c
                    if (INT_MAX < num) /* yeah, right */
Packit c4476c
                        num = INT_MAX;
Packit c4476c
Packit c4476c
                    r = BIO_nread(io1, &dataptr, (int)num);
Packit c4476c
                    assert(r > 0);
Packit c4476c
                    assert(r <= (int)num);
Packit c4476c
                    /*
Packit c4476c
                     * possibly r < num (non-contiguous data)
Packit c4476c
                     */
Packit c4476c
                    num = r;
Packit c4476c
                    r = BIO_write(io2, dataptr, (int)num);
Packit c4476c
                    if (r != (int)num) { /* can't happen */
Packit c4476c
                        fprintf(stderr, "ERROR: BIO_write could not write "
Packit c4476c
                                "BIO_ctrl_get_write_guarantee() bytes");
Packit c4476c
                        goto err;
Packit c4476c
                    }
Packit c4476c
                    progress = 1;
Packit c4476c
Packit c4476c
                    if (debug)
Packit c4476c
                        printf((io1 == client_io) ?
Packit c4476c
                               "C->S relaying: %d bytes\n" :
Packit c4476c
                               "S->C relaying: %d bytes\n", (int)num);
Packit c4476c
                }
Packit c4476c
            }
Packit c4476c
            while (r1 && r2);
Packit c4476c
Packit c4476c
            /* io2 to io1 */
Packit c4476c
            {
Packit c4476c
                size_t num;
Packit c4476c
                int r;
Packit c4476c
Packit c4476c
                r1 = BIO_ctrl_pending(io2);
Packit c4476c
                r2 = BIO_ctrl_get_read_request(io1);
Packit c4476c
                /*
Packit c4476c
                 * here we could use ..._get_write_guarantee instead of
Packit c4476c
                 * ..._get_read_request, but by using the latter we test
Packit c4476c
                 * restartability of the SSL implementation more thoroughly
Packit c4476c
                 */
Packit c4476c
                num = r1;
Packit c4476c
                if (r2 < num)
Packit c4476c
                    num = r2;
Packit c4476c
                if (num) {
Packit c4476c
                    char *dataptr;
Packit c4476c
Packit c4476c
                    if (INT_MAX < num)
Packit c4476c
                        num = INT_MAX;
Packit c4476c
Packit c4476c
                    if (num > 1)
Packit c4476c
                        --num;  /* test restartability even more thoroughly */
Packit c4476c
Packit c4476c
                    r = BIO_nwrite0(io1, &dataptr);
Packit c4476c
                    assert(r > 0);
Packit c4476c
                    if (r < (int)num)
Packit c4476c
                        num = r;
Packit c4476c
                    r = BIO_read(io2, dataptr, (int)num);
Packit c4476c
                    if (r != (int)num) { /* can't happen */
Packit c4476c
                        fprintf(stderr, "ERROR: BIO_read could not read "
Packit c4476c
                                "BIO_ctrl_pending() bytes");
Packit c4476c
                        goto err;
Packit c4476c
                    }
Packit c4476c
                    progress = 1;
Packit c4476c
                    r = BIO_nwrite(io1, &dataptr, (int)num);
Packit c4476c
                    if (r != (int)num) { /* can't happen */
Packit c4476c
                        fprintf(stderr, "ERROR: BIO_nwrite() did not accept "
Packit c4476c
                                "BIO_nwrite0() bytes");
Packit c4476c
                        goto err;
Packit c4476c
                    }
Packit c4476c
Packit c4476c
                    if (debug)
Packit c4476c
                        printf((io2 == client_io) ?
Packit c4476c
                               "C->S relaying: %d bytes\n" :
Packit c4476c
                               "S->C relaying: %d bytes\n", (int)num);
Packit c4476c
                }
Packit c4476c
            }                   /* no loop, BIO_ctrl_get_read_request now
Packit c4476c
                                 * returns 0 anyway */
Packit c4476c
Packit c4476c
            if (!progress && !prev_progress)
Packit c4476c
                if (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0) {
Packit c4476c
                    fprintf(stderr, "ERROR: got stuck\n");
Packit c4476c
                    fprintf(stderr, " ERROR.\n");
Packit c4476c
                    goto err;
Packit c4476c
                }
Packit c4476c
            prev_progress = progress;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
    while (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0);
Packit c4476c
Packit c4476c
    if (verbose)
Packit c4476c
        print_details(c_ssl, "DONE via BIO pair: ");
Packit c4476c
#ifndef OPENSSL_NO_NEXTPROTONEG
Packit c4476c
    if (verify_npn(c_ssl, s_ssl) < 0)
Packit c4476c
        goto end;
Packit c4476c
#endif
Packit c4476c
    if (verify_serverinfo() < 0) {
Packit c4476c
        fprintf(stderr, "Server info verify error\n");
Packit c4476c
        goto err;
Packit c4476c
    }
Packit c4476c
    if (verify_alpn(c_ssl, s_ssl) < 0
Packit c4476c
            || verify_servername(c_ssl, s_ssl) < 0)
Packit c4476c
        goto err;
Packit c4476c
Packit c4476c
    if (custom_ext_error) {
Packit c4476c
        fprintf(stderr, "Custom extension error\n");
Packit c4476c
        goto err;
Packit c4476c
    }
Packit c4476c
Packit c4476c
#ifndef OPENSSL_NO_NEXTPROTONEG
Packit c4476c
 end:
Packit c4476c
#endif
Packit c4476c
    ret = EXIT_SUCCESS;
Packit c4476c
Packit c4476c
 err:
Packit c4476c
    ERR_print_errors(bio_err);
Packit c4476c
Packit c4476c
    BIO_free(server);
Packit c4476c
    BIO_free(server_io);
Packit c4476c
    BIO_free(client);
Packit c4476c
    BIO_free(client_io);
Packit c4476c
    BIO_free(s_ssl_bio);
Packit c4476c
    BIO_free(c_ssl_bio);
Packit c4476c
Packit c4476c
    if (should_negotiate != NULL && strcmp(should_negotiate, "fail-client") == 0)
Packit c4476c
        ret = (err_in_client != 0) ? EXIT_SUCCESS : EXIT_FAILURE;
Packit c4476c
    else if (should_negotiate != NULL && strcmp(should_negotiate, "fail-server") == 0)
Packit c4476c
        ret = (err_in_server != 0) ? EXIT_SUCCESS : EXIT_FAILURE;
Packit c4476c
Packit c4476c
    return ret;
Packit c4476c
}
Packit c4476c
Packit c4476c
#define W_READ  1
Packit c4476c
#define W_WRITE 2
Packit c4476c
#define C_DONE  1
Packit c4476c
#define S_DONE  2
Packit c4476c
Packit c4476c
int doit(SSL *s_ssl, SSL *c_ssl, long count)
Packit c4476c
{
Packit c4476c
    char *cbuf = NULL, *sbuf = NULL;
Packit c4476c
    long bufsiz;
Packit c4476c
    long cw_num = count, cr_num = count;
Packit c4476c
    long sw_num = count, sr_num = count;
Packit c4476c
    int ret = EXIT_FAILURE;
Packit c4476c
    BIO *c_to_s = NULL;
Packit c4476c
    BIO *s_to_c = NULL;
Packit c4476c
    BIO *c_bio = NULL;
Packit c4476c
    BIO *s_bio = NULL;
Packit c4476c
    int c_r, c_w, s_r, s_w;
Packit c4476c
    int i, j;
Packit c4476c
    int done = 0;
Packit c4476c
    int c_write, s_write;
Packit c4476c
    int do_server = 0, do_client = 0;
Packit c4476c
    int max_frag = 5 * 1024;
Packit c4476c
    int err_in_client = 0;
Packit c4476c
    int err_in_server = 0;
Packit c4476c
Packit c4476c
    bufsiz = count > 40 * 1024 ? 40 * 1024 : count;
Packit c4476c
Packit c4476c
    if ((cbuf = OPENSSL_zalloc(bufsiz)) == NULL)
Packit c4476c
        goto err;
Packit c4476c
    if ((sbuf = OPENSSL_zalloc(bufsiz)) == NULL)
Packit c4476c
        goto err;
Packit c4476c
Packit c4476c
    c_to_s = BIO_new(BIO_s_mem());
Packit c4476c
    s_to_c = BIO_new(BIO_s_mem());
Packit c4476c
    if ((s_to_c == NULL) || (c_to_s == NULL)) {
Packit c4476c
        ERR_print_errors(bio_err);
Packit c4476c
        goto err;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    c_bio = BIO_new(BIO_f_ssl());
Packit c4476c
    s_bio = BIO_new(BIO_f_ssl());
Packit c4476c
    if ((c_bio == NULL) || (s_bio == NULL)) {
Packit c4476c
        ERR_print_errors(bio_err);
Packit c4476c
        goto err;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    SSL_set_connect_state(c_ssl);
Packit c4476c
    SSL_set_bio(c_ssl, s_to_c, c_to_s);
Packit c4476c
    SSL_set_max_send_fragment(c_ssl, max_frag);
Packit c4476c
    BIO_set_ssl(c_bio, c_ssl, BIO_NOCLOSE);
Packit c4476c
Packit c4476c
    /*
Packit c4476c
     * We've just given our ref to these BIOs to c_ssl. We need another one to
Packit c4476c
     * give to s_ssl
Packit c4476c
     */
Packit c4476c
    if (!BIO_up_ref(c_to_s)) {
Packit c4476c
        /* c_to_s and s_to_c will get freed when we free c_ssl */
Packit c4476c
        c_to_s = NULL;
Packit c4476c
        s_to_c = NULL;
Packit c4476c
        goto err;
Packit c4476c
    }
Packit c4476c
    if (!BIO_up_ref(s_to_c)) {
Packit c4476c
        /* s_to_c will get freed when we free c_ssl */
Packit c4476c
        s_to_c = NULL;
Packit c4476c
        goto err;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    SSL_set_accept_state(s_ssl);
Packit c4476c
    SSL_set_bio(s_ssl, c_to_s, s_to_c);
Packit c4476c
Packit c4476c
    /* We've used up all our refs to these now */
Packit c4476c
    c_to_s = NULL;
Packit c4476c
    s_to_c = NULL;
Packit c4476c
Packit c4476c
    SSL_set_max_send_fragment(s_ssl, max_frag);
Packit c4476c
    BIO_set_ssl(s_bio, s_ssl, BIO_NOCLOSE);
Packit c4476c
Packit c4476c
    c_r = 0;
Packit c4476c
    s_r = 1;
Packit c4476c
    c_w = 1;
Packit c4476c
    s_w = 0;
Packit c4476c
    c_write = 1, s_write = 0;
Packit c4476c
Packit c4476c
    /* We can always do writes */
Packit c4476c
    for (;;) {
Packit c4476c
        do_server = 0;
Packit c4476c
        do_client = 0;
Packit c4476c
Packit c4476c
        i = (int)BIO_pending(s_bio);
Packit c4476c
        if ((i && s_r) || s_w)
Packit c4476c
            do_server = 1;
Packit c4476c
Packit c4476c
        i = (int)BIO_pending(c_bio);
Packit c4476c
        if ((i && c_r) || c_w)
Packit c4476c
            do_client = 1;
Packit c4476c
Packit c4476c
        if (do_server && debug) {
Packit c4476c
            if (SSL_in_init(s_ssl))
Packit c4476c
                printf("server waiting in SSL_accept - %s\n",
Packit c4476c
                       SSL_state_string_long(s_ssl));
Packit c4476c
        }
Packit c4476c
Packit c4476c
        if (do_client && debug) {
Packit c4476c
            if (SSL_in_init(c_ssl))
Packit c4476c
                printf("client waiting in SSL_connect - %s\n",
Packit c4476c
                       SSL_state_string_long(c_ssl));
Packit c4476c
        }
Packit c4476c
Packit c4476c
        if (!do_client && !do_server) {
Packit c4476c
            fprintf(stdout, "ERROR IN STARTUP\n");
Packit c4476c
            ERR_print_errors(bio_err);
Packit c4476c
            goto err;
Packit c4476c
        }
Packit c4476c
        if (do_client && !(done & C_DONE)) {
Packit c4476c
            if (c_write) {
Packit c4476c
                j = (cw_num > bufsiz) ? (int)bufsiz : (int)cw_num;
Packit c4476c
                i = BIO_write(c_bio, cbuf, j);
Packit c4476c
                if (i < 0) {
Packit c4476c
                    c_r = 0;
Packit c4476c
                    c_w = 0;
Packit c4476c
                    if (BIO_should_retry(c_bio)) {
Packit c4476c
                        if (BIO_should_read(c_bio))
Packit c4476c
                            c_r = 1;
Packit c4476c
                        if (BIO_should_write(c_bio))
Packit c4476c
                            c_w = 1;
Packit c4476c
                    } else {
Packit c4476c
                        fprintf(stderr, "ERROR in CLIENT\n");
Packit c4476c
                        err_in_client = 1;
Packit c4476c
                        ERR_print_errors(bio_err);
Packit c4476c
                        goto err;
Packit c4476c
                    }
Packit c4476c
                } else if (i == 0) {
Packit c4476c
                    fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
Packit c4476c
                    goto err;
Packit c4476c
                } else {
Packit c4476c
                    if (debug)
Packit c4476c
                        printf("client wrote %d\n", i);
Packit c4476c
                    /* ok */
Packit c4476c
                    s_r = 1;
Packit c4476c
                    c_write = 0;
Packit c4476c
                    cw_num -= i;
Packit c4476c
                    if (max_frag > 1029)
Packit c4476c
                        SSL_set_max_send_fragment(c_ssl, max_frag -= 5);
Packit c4476c
                }
Packit c4476c
            } else {
Packit c4476c
                i = BIO_read(c_bio, cbuf, bufsiz);
Packit c4476c
                if (i < 0) {
Packit c4476c
                    c_r = 0;
Packit c4476c
                    c_w = 0;
Packit c4476c
                    if (BIO_should_retry(c_bio)) {
Packit c4476c
                        if (BIO_should_read(c_bio))
Packit c4476c
                            c_r = 1;
Packit c4476c
                        if (BIO_should_write(c_bio))
Packit c4476c
                            c_w = 1;
Packit c4476c
                    } else {
Packit c4476c
                        fprintf(stderr, "ERROR in CLIENT\n");
Packit c4476c
                        err_in_client = 1;
Packit c4476c
                        ERR_print_errors(bio_err);
Packit c4476c
                        goto err;
Packit c4476c
                    }
Packit c4476c
                } else if (i == 0) {
Packit c4476c
                    fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
Packit c4476c
                    goto err;
Packit c4476c
                } else {
Packit c4476c
                    if (debug)
Packit c4476c
                        printf("client read %d\n", i);
Packit c4476c
                    cr_num -= i;
Packit c4476c
                    if (sw_num > 0) {
Packit c4476c
                        s_write = 1;
Packit c4476c
                        s_w = 1;
Packit c4476c
                    }
Packit c4476c
                    if (cr_num <= 0) {
Packit c4476c
                        s_write = 1;
Packit c4476c
                        s_w = 1;
Packit c4476c
                        done = S_DONE | C_DONE;
Packit c4476c
                    }
Packit c4476c
                }
Packit c4476c
            }
Packit c4476c
        }
Packit c4476c
Packit c4476c
        if (do_server && !(done & S_DONE)) {
Packit c4476c
            if (!s_write) {
Packit c4476c
                i = BIO_read(s_bio, sbuf, bufsiz);
Packit c4476c
                if (i < 0) {
Packit c4476c
                    s_r = 0;
Packit c4476c
                    s_w = 0;
Packit c4476c
                    if (BIO_should_retry(s_bio)) {
Packit c4476c
                        if (BIO_should_read(s_bio))
Packit c4476c
                            s_r = 1;
Packit c4476c
                        if (BIO_should_write(s_bio))
Packit c4476c
                            s_w = 1;
Packit c4476c
                    } else {
Packit c4476c
                        fprintf(stderr, "ERROR in SERVER\n");
Packit c4476c
                        err_in_server = 1;
Packit c4476c
                        ERR_print_errors(bio_err);
Packit c4476c
                        goto err;
Packit c4476c
                    }
Packit c4476c
                } else if (i == 0) {
Packit c4476c
                    ERR_print_errors(bio_err);
Packit c4476c
                    fprintf(stderr,
Packit c4476c
                            "SSL SERVER STARTUP FAILED in SSL_read\n");
Packit c4476c
                    goto err;
Packit c4476c
                } else {
Packit c4476c
                    if (debug)
Packit c4476c
                        printf("server read %d\n", i);
Packit c4476c
                    sr_num -= i;
Packit c4476c
                    if (cw_num > 0) {
Packit c4476c
                        c_write = 1;
Packit c4476c
                        c_w = 1;
Packit c4476c
                    }
Packit c4476c
                    if (sr_num <= 0) {
Packit c4476c
                        s_write = 1;
Packit c4476c
                        s_w = 1;
Packit c4476c
                        c_write = 0;
Packit c4476c
                    }
Packit c4476c
                }
Packit c4476c
            } else {
Packit c4476c
                j = (sw_num > bufsiz) ? (int)bufsiz : (int)sw_num;
Packit c4476c
                i = BIO_write(s_bio, sbuf, j);
Packit c4476c
                if (i < 0) {
Packit c4476c
                    s_r = 0;
Packit c4476c
                    s_w = 0;
Packit c4476c
                    if (BIO_should_retry(s_bio)) {
Packit c4476c
                        if (BIO_should_read(s_bio))
Packit c4476c
                            s_r = 1;
Packit c4476c
                        if (BIO_should_write(s_bio))
Packit c4476c
                            s_w = 1;
Packit c4476c
                    } else {
Packit c4476c
                        fprintf(stderr, "ERROR in SERVER\n");
Packit c4476c
                        err_in_server = 1;
Packit c4476c
                        ERR_print_errors(bio_err);
Packit c4476c
                        goto err;
Packit c4476c
                    }
Packit c4476c
                } else if (i == 0) {
Packit c4476c
                    ERR_print_errors(bio_err);
Packit c4476c
                    fprintf(stderr,
Packit c4476c
                            "SSL SERVER STARTUP FAILED in SSL_write\n");
Packit c4476c
                    goto err;
Packit c4476c
                } else {
Packit c4476c
                    if (debug)
Packit c4476c
                        printf("server wrote %d\n", i);
Packit c4476c
                    sw_num -= i;
Packit c4476c
                    s_write = 0;
Packit c4476c
                    c_r = 1;
Packit c4476c
                    if (sw_num <= 0)
Packit c4476c
                        done |= S_DONE;
Packit c4476c
                    if (max_frag > 1029)
Packit c4476c
                        SSL_set_max_send_fragment(s_ssl, max_frag -= 5);
Packit c4476c
                }
Packit c4476c
            }
Packit c4476c
        }
Packit c4476c
Packit c4476c
        if ((done & S_DONE) && (done & C_DONE))
Packit c4476c
            break;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (verbose)
Packit c4476c
        print_details(c_ssl, "DONE: ");
Packit c4476c
#ifndef OPENSSL_NO_NEXTPROTONEG
Packit c4476c
    if (verify_npn(c_ssl, s_ssl) < 0)
Packit c4476c
        goto err;
Packit c4476c
#endif
Packit c4476c
    if (verify_serverinfo() < 0) {
Packit c4476c
        fprintf(stderr, "Server info verify error\n");
Packit c4476c
        goto err;
Packit c4476c
    }
Packit c4476c
    if (custom_ext_error) {
Packit c4476c
        fprintf(stderr, "Custom extension error\n");
Packit c4476c
        goto err;
Packit c4476c
    }
Packit c4476c
    ret = EXIT_SUCCESS;
Packit c4476c
 err:
Packit c4476c
    BIO_free(c_to_s);
Packit c4476c
    BIO_free(s_to_c);
Packit c4476c
    BIO_free_all(c_bio);
Packit c4476c
    BIO_free_all(s_bio);
Packit c4476c
    OPENSSL_free(cbuf);
Packit c4476c
    OPENSSL_free(sbuf);
Packit c4476c
Packit c4476c
    if (should_negotiate != NULL && strcmp(should_negotiate, "fail-client") == 0)
Packit c4476c
        ret = (err_in_client != 0) ? EXIT_SUCCESS : EXIT_FAILURE;
Packit c4476c
    else if (should_negotiate != NULL && strcmp(should_negotiate, "fail-server") == 0)
Packit c4476c
        ret = (err_in_server != 0) ? EXIT_SUCCESS : EXIT_FAILURE;
Packit c4476c
Packit c4476c
    return ret;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int verify_callback(int ok, X509_STORE_CTX *ctx)
Packit c4476c
{
Packit c4476c
    char *s, buf[256];
Packit c4476c
Packit c4476c
    s = X509_NAME_oneline(X509_get_subject_name(X509_STORE_CTX_get_current_cert(ctx)),
Packit c4476c
                          buf, sizeof(buf));
Packit c4476c
    if (s != NULL) {
Packit c4476c
        if (ok)
Packit c4476c
            printf("depth=%d %s\n", X509_STORE_CTX_get_error_depth(ctx), buf);
Packit c4476c
        else {
Packit c4476c
            fprintf(stderr, "depth=%d error=%d %s\n",
Packit c4476c
                    X509_STORE_CTX_get_error_depth(ctx),
Packit c4476c
                    X509_STORE_CTX_get_error(ctx), buf);
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (ok == 0) {
Packit c4476c
        int i = X509_STORE_CTX_get_error(ctx);
Packit c4476c
Packit c4476c
        switch (i) {
Packit c4476c
        default:
Packit c4476c
            fprintf(stderr, "Error string: %s\n",
Packit c4476c
                    X509_verify_cert_error_string(i));
Packit c4476c
            break;
Packit c4476c
        case X509_V_ERR_CERT_NOT_YET_VALID:
Packit c4476c
        case X509_V_ERR_CERT_HAS_EXPIRED:
Packit c4476c
        case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
Packit c4476c
            ok = 1;
Packit c4476c
            break;
Packit c4476c
        }
Packit c4476c
    }
Packit c4476c
Packit c4476c
    return ok;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int app_verify_callback(X509_STORE_CTX *ctx, void *arg)
Packit c4476c
{
Packit c4476c
    int ok = 1;
Packit c4476c
    struct app_verify_arg *cb_arg = arg;
Packit c4476c
Packit c4476c
    if (cb_arg->app_verify) {
Packit c4476c
        char *s = NULL, buf[256];
Packit c4476c
        X509 *c = X509_STORE_CTX_get0_cert(ctx);
Packit c4476c
Packit c4476c
        printf("In app_verify_callback, allowing cert. ");
Packit c4476c
        printf("Arg is: %s\n", cb_arg->string);
Packit c4476c
        printf("Finished printing do we have a context? 0x%p a cert? 0x%p\n",
Packit c4476c
                (void *)ctx, (void *)c);
Packit c4476c
        if (c)
Packit c4476c
            s = X509_NAME_oneline(X509_get_subject_name(c), buf, 256);
Packit c4476c
        if (s != NULL) {
Packit c4476c
            printf("cert depth=%d %s\n",
Packit c4476c
                    X509_STORE_CTX_get_error_depth(ctx), buf);
Packit c4476c
        }
Packit c4476c
        return 1;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    ok = X509_verify_cert(ctx);
Packit c4476c
Packit c4476c
    return ok;
Packit c4476c
}
Packit c4476c
Packit c4476c
#ifndef OPENSSL_NO_DH
Packit c4476c
/*-
Packit c4476c
 * These DH parameters have been generated as follows:
Packit c4476c
 *    $ openssl dhparam -C -noout 512
Packit c4476c
 *    $ openssl dhparam -C -noout 1024
Packit c4476c
 *    $ openssl dhparam -C -noout -dsaparam 1024
Packit c4476c
 * (The third function has been renamed to avoid name conflicts.)
Packit c4476c
 */
Packit c4476c
static DH *get_dh512(void)
Packit c4476c
{
Packit c4476c
    static unsigned char dh512_p[] = {
Packit c4476c
        0xCB, 0xC8, 0xE1, 0x86, 0xD0, 0x1F, 0x94, 0x17, 0xA6, 0x99, 0xF0,
Packit c4476c
        0xC6,
Packit c4476c
        0x1F, 0x0D, 0xAC, 0xB6, 0x25, 0x3E, 0x06, 0x39, 0xCA, 0x72, 0x04,
Packit c4476c
        0xB0,
Packit c4476c
        0x6E, 0xDA, 0xC0, 0x61, 0xE6, 0x7A, 0x77, 0x25, 0xE8, 0x3B, 0xB9,
Packit c4476c
        0x5F,
Packit c4476c
        0x9A, 0xB6, 0xB5, 0xFE, 0x99, 0x0B, 0xA1, 0x93, 0x4E, 0x35, 0x33,
Packit c4476c
        0xB8,
Packit c4476c
        0xE1, 0xF1, 0x13, 0x4F, 0x59, 0x1A, 0xD2, 0x57, 0xC0, 0x26, 0x21,
Packit c4476c
        0x33,
Packit c4476c
        0x02, 0xC5, 0xAE, 0x23,
Packit c4476c
    };
Packit c4476c
    static unsigned char dh512_g[] = {
Packit c4476c
        0x02,
Packit c4476c
    };
Packit c4476c
    DH *dh;
Packit c4476c
    BIGNUM *p, *g;
Packit c4476c
Packit c4476c
    if ((dh = DH_new()) == NULL)
Packit c4476c
        return NULL;
Packit c4476c
    p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL);
Packit c4476c
    g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL);
Packit c4476c
    if ((p == NULL) || (g == NULL) || !DH_set0_pqg(dh, p, NULL, g)) {
Packit c4476c
        DH_free(dh);
Packit c4476c
        BN_free(p);
Packit c4476c
        BN_free(g);
Packit c4476c
        return NULL;
Packit c4476c
    }
Packit c4476c
    return dh;
Packit c4476c
}
Packit c4476c
Packit c4476c
static DH *get_dh1024(void)
Packit c4476c
{
Packit c4476c
    static unsigned char dh1024_p[] = {
Packit c4476c
        0xF8, 0x81, 0x89, 0x7D, 0x14, 0x24, 0xC5, 0xD1, 0xE6, 0xF7, 0xBF,
Packit c4476c
        0x3A,
Packit c4476c
        0xE4, 0x90, 0xF4, 0xFC, 0x73, 0xFB, 0x34, 0xB5, 0xFA, 0x4C, 0x56,
Packit c4476c
        0xA2,
Packit c4476c
        0xEA, 0xA7, 0xE9, 0xC0, 0xC0, 0xCE, 0x89, 0xE1, 0xFA, 0x63, 0x3F,
Packit c4476c
        0xB0,
Packit c4476c
        0x6B, 0x32, 0x66, 0xF1, 0xD1, 0x7B, 0xB0, 0x00, 0x8F, 0xCA, 0x87,
Packit c4476c
        0xC2,
Packit c4476c
        0xAE, 0x98, 0x89, 0x26, 0x17, 0xC2, 0x05, 0xD2, 0xEC, 0x08, 0xD0,
Packit c4476c
        0x8C,
Packit c4476c
        0xFF, 0x17, 0x52, 0x8C, 0xC5, 0x07, 0x93, 0x03, 0xB1, 0xF6, 0x2F,
Packit c4476c
        0xB8,
Packit c4476c
        0x1C, 0x52, 0x47, 0x27, 0x1B, 0xDB, 0xD1, 0x8D, 0x9D, 0x69, 0x1D,
Packit c4476c
        0x52,
Packit c4476c
        0x4B, 0x32, 0x81, 0xAA, 0x7F, 0x00, 0xC8, 0xDC, 0xE6, 0xD9, 0xCC,
Packit c4476c
        0xC1,
Packit c4476c
        0x11, 0x2D, 0x37, 0x34, 0x6C, 0xEA, 0x02, 0x97, 0x4B, 0x0E, 0xBB,
Packit c4476c
        0xB1,
Packit c4476c
        0x71, 0x33, 0x09, 0x15, 0xFD, 0xDD, 0x23, 0x87, 0x07, 0x5E, 0x89,
Packit c4476c
        0xAB,
Packit c4476c
        0x6B, 0x7C, 0x5F, 0xEC, 0xA6, 0x24, 0xDC, 0x53,
Packit c4476c
    };
Packit c4476c
    static unsigned char dh1024_g[] = {
Packit c4476c
        0x02,
Packit c4476c
    };
Packit c4476c
    DH *dh;
Packit c4476c
    BIGNUM *p, *g;
Packit c4476c
Packit c4476c
    if ((dh = DH_new()) == NULL)
Packit c4476c
        return NULL;
Packit c4476c
    p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
Packit c4476c
    g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
Packit c4476c
    if ((p == NULL) || (g == NULL) || !DH_set0_pqg(dh, p, NULL, g)) {
Packit c4476c
        DH_free(dh);
Packit c4476c
        BN_free(p);
Packit c4476c
        BN_free(g);
Packit c4476c
        return NULL;
Packit c4476c
    }
Packit c4476c
    return dh;
Packit c4476c
}
Packit c4476c
Packit c4476c
static DH *get_dh1024dsa(void)
Packit c4476c
{
Packit c4476c
    static unsigned char dh1024_p[] = {
Packit c4476c
        0xC8, 0x00, 0xF7, 0x08, 0x07, 0x89, 0x4D, 0x90, 0x53, 0xF3, 0xD5,
Packit c4476c
        0x00,
Packit c4476c
        0x21, 0x1B, 0xF7, 0x31, 0xA6, 0xA2, 0xDA, 0x23, 0x9A, 0xC7, 0x87,
Packit c4476c
        0x19,
Packit c4476c
        0x3B, 0x47, 0xB6, 0x8C, 0x04, 0x6F, 0xFF, 0xC6, 0x9B, 0xB8, 0x65,
Packit c4476c
        0xD2,
Packit c4476c
        0xC2, 0x5F, 0x31, 0x83, 0x4A, 0xA7, 0x5F, 0x2F, 0x88, 0x38, 0xB6,
Packit c4476c
        0x55,
Packit c4476c
        0xCF, 0xD9, 0x87, 0x6D, 0x6F, 0x9F, 0xDA, 0xAC, 0xA6, 0x48, 0xAF,
Packit c4476c
        0xFC,
Packit c4476c
        0x33, 0x84, 0x37, 0x5B, 0x82, 0x4A, 0x31, 0x5D, 0xE7, 0xBD, 0x52,
Packit c4476c
        0x97,
Packit c4476c
        0xA1, 0x77, 0xBF, 0x10, 0x9E, 0x37, 0xEA, 0x64, 0xFA, 0xCA, 0x28,
Packit c4476c
        0x8D,
Packit c4476c
        0x9D, 0x3B, 0xD2, 0x6E, 0x09, 0x5C, 0x68, 0xC7, 0x45, 0x90, 0xFD,
Packit c4476c
        0xBB,
Packit c4476c
        0x70, 0xC9, 0x3A, 0xBB, 0xDF, 0xD4, 0x21, 0x0F, 0xC4, 0x6A, 0x3C,
Packit c4476c
        0xF6,
Packit c4476c
        0x61, 0xCF, 0x3F, 0xD6, 0x13, 0xF1, 0x5F, 0xBC, 0xCF, 0xBC, 0x26,
Packit c4476c
        0x9E,
Packit c4476c
        0xBC, 0x0B, 0xBD, 0xAB, 0x5D, 0xC9, 0x54, 0x39,
Packit c4476c
    };
Packit c4476c
    static unsigned char dh1024_g[] = {
Packit c4476c
        0x3B, 0x40, 0x86, 0xE7, 0xF3, 0x6C, 0xDE, 0x67, 0x1C, 0xCC, 0x80,
Packit c4476c
        0x05,
Packit c4476c
        0x5A, 0xDF, 0xFE, 0xBD, 0x20, 0x27, 0x74, 0x6C, 0x24, 0xC9, 0x03,
Packit c4476c
        0xF3,
Packit c4476c
        0xE1, 0x8D, 0xC3, 0x7D, 0x98, 0x27, 0x40, 0x08, 0xB8, 0x8C, 0x6A,
Packit c4476c
        0xE9,
Packit c4476c
        0xBB, 0x1A, 0x3A, 0xD6, 0x86, 0x83, 0x5E, 0x72, 0x41, 0xCE, 0x85,
Packit c4476c
        0x3C,
Packit c4476c
        0xD2, 0xB3, 0xFC, 0x13, 0xCE, 0x37, 0x81, 0x9E, 0x4C, 0x1C, 0x7B,
Packit c4476c
        0x65,
Packit c4476c
        0xD3, 0xE6, 0xA6, 0x00, 0xF5, 0x5A, 0x95, 0x43, 0x5E, 0x81, 0xCF,
Packit c4476c
        0x60,
Packit c4476c
        0xA2, 0x23, 0xFC, 0x36, 0xA7, 0x5D, 0x7A, 0x4C, 0x06, 0x91, 0x6E,
Packit c4476c
        0xF6,
Packit c4476c
        0x57, 0xEE, 0x36, 0xCB, 0x06, 0xEA, 0xF5, 0x3D, 0x95, 0x49, 0xCB,
Packit c4476c
        0xA7,
Packit c4476c
        0xDD, 0x81, 0xDF, 0x80, 0x09, 0x4A, 0x97, 0x4D, 0xA8, 0x22, 0x72,
Packit c4476c
        0xA1,
Packit c4476c
        0x7F, 0xC4, 0x70, 0x56, 0x70, 0xE8, 0x20, 0x10, 0x18, 0x8F, 0x2E,
Packit c4476c
        0x60,
Packit c4476c
        0x07, 0xE7, 0x68, 0x1A, 0x82, 0x5D, 0x32, 0xA2,
Packit c4476c
    };
Packit c4476c
    DH *dh;
Packit c4476c
    BIGNUM *p, *g;
Packit c4476c
Packit c4476c
    if ((dh = DH_new()) == NULL)
Packit c4476c
        return NULL;
Packit c4476c
    p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
Packit c4476c
    g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
Packit c4476c
    if ((p == NULL) || (g == NULL) || !DH_set0_pqg(dh, p, NULL, g)) {
Packit c4476c
        DH_free(dh);
Packit c4476c
        BN_free(p);
Packit c4476c
        BN_free(g);
Packit c4476c
        return NULL;
Packit c4476c
    }
Packit c4476c
    DH_set_length(dh, 160);
Packit c4476c
    return dh;
Packit c4476c
}
Packit c4476c
#endif
Packit c4476c
Packit c4476c
#ifndef OPENSSL_NO_PSK
Packit c4476c
/* convert the PSK key (psk_key) in ascii to binary (psk) */
Packit c4476c
static int psk_key2bn(const char *pskkey, unsigned char *psk,
Packit c4476c
                      unsigned int max_psk_len)
Packit c4476c
{
Packit c4476c
    int ret;
Packit c4476c
    BIGNUM *bn = NULL;
Packit c4476c
Packit c4476c
    ret = BN_hex2bn(&bn, pskkey);
Packit c4476c
    if (!ret) {
Packit c4476c
        BIO_printf(bio_err, "Could not convert PSK key '%s' to BIGNUM\n",
Packit c4476c
                   pskkey);
Packit c4476c
        BN_free(bn);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
    if (BN_num_bytes(bn) > (int)max_psk_len) {
Packit c4476c
        BIO_printf(bio_err,
Packit c4476c
                   "psk buffer of callback is too small (%d) for key (%d)\n",
Packit c4476c
                   max_psk_len, BN_num_bytes(bn));
Packit c4476c
        BN_free(bn);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
    ret = BN_bn2bin(bn, psk);
Packit c4476c
    BN_free(bn);
Packit c4476c
    return ret;
Packit c4476c
}
Packit c4476c
Packit c4476c
static unsigned int psk_client_callback(SSL *ssl, const char *hint,
Packit c4476c
                                        char *identity,
Packit c4476c
                                        unsigned int max_identity_len,
Packit c4476c
                                        unsigned char *psk,
Packit c4476c
                                        unsigned int max_psk_len)
Packit c4476c
{
Packit c4476c
    int ret;
Packit c4476c
    unsigned int psk_len = 0;
Packit c4476c
Packit c4476c
    ret = BIO_snprintf(identity, max_identity_len, "Client_identity");
Packit c4476c
    if (ret < 0)
Packit c4476c
        goto out_err;
Packit c4476c
    if (debug)
Packit c4476c
        fprintf(stderr, "client: created identity '%s' len=%d\n", identity,
Packit c4476c
                ret);
Packit c4476c
    ret = psk_key2bn(psk_key, psk, max_psk_len);
Packit c4476c
    if (ret < 0)
Packit c4476c
        goto out_err;
Packit c4476c
    psk_len = ret;
Packit c4476c
 out_err:
Packit c4476c
    return psk_len;
Packit c4476c
}
Packit c4476c
Packit c4476c
static unsigned int psk_server_callback(SSL *ssl, const char *identity,
Packit c4476c
                                        unsigned char *psk,
Packit c4476c
                                        unsigned int max_psk_len)
Packit c4476c
{
Packit c4476c
    unsigned int psk_len = 0;
Packit c4476c
Packit c4476c
    if (strcmp(identity, "Client_identity") != 0) {
Packit c4476c
        BIO_printf(bio_err, "server: PSK error: client identity not found\n");
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
    psk_len = psk_key2bn(psk_key, psk, max_psk_len);
Packit c4476c
    return psk_len;
Packit c4476c
}
Packit c4476c
#endif