1*319de9d2Stb /* $OpenBSD: ssltest.c,v 1.45 2024/03/01 03:45:16 tb Exp $ */
2e90e4cafSjsing /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3e90e4cafSjsing * All rights reserved.
4e90e4cafSjsing *
5e90e4cafSjsing * This package is an SSL implementation written
6e90e4cafSjsing * by Eric Young (eay@cryptsoft.com).
7e90e4cafSjsing * The implementation was written so as to conform with Netscapes SSL.
8e90e4cafSjsing *
9e90e4cafSjsing * This library is free for commercial and non-commercial use as long as
10e90e4cafSjsing * the following conditions are aheared to. The following conditions
11e90e4cafSjsing * apply to all code found in this distribution, be it the RC4, RSA,
12e90e4cafSjsing * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13e90e4cafSjsing * included with this distribution is covered by the same copyright terms
14e90e4cafSjsing * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15e90e4cafSjsing *
16e90e4cafSjsing * Copyright remains Eric Young's, and as such any Copyright notices in
17e90e4cafSjsing * the code are not to be removed.
18e90e4cafSjsing * If this package is used in a product, Eric Young should be given attribution
19e90e4cafSjsing * as the author of the parts of the library used.
20e90e4cafSjsing * This can be in the form of a textual message at program startup or
21e90e4cafSjsing * in documentation (online or textual) provided with the package.
22e90e4cafSjsing *
23e90e4cafSjsing * Redistribution and use in source and binary forms, with or without
24e90e4cafSjsing * modification, are permitted provided that the following conditions
25e90e4cafSjsing * are met:
26e90e4cafSjsing * 1. Redistributions of source code must retain the copyright
27e90e4cafSjsing * notice, this list of conditions and the following disclaimer.
28e90e4cafSjsing * 2. Redistributions in binary form must reproduce the above copyright
29e90e4cafSjsing * notice, this list of conditions and the following disclaimer in the
30e90e4cafSjsing * documentation and/or other materials provided with the distribution.
31e90e4cafSjsing * 3. All advertising materials mentioning features or use of this software
32e90e4cafSjsing * must display the following acknowledgement:
33e90e4cafSjsing * "This product includes cryptographic software written by
34e90e4cafSjsing * Eric Young (eay@cryptsoft.com)"
35e90e4cafSjsing * The word 'cryptographic' can be left out if the rouines from the library
36e90e4cafSjsing * being used are not cryptographic related :-).
37e90e4cafSjsing * 4. If you include any Windows specific code (or a derivative thereof) from
38e90e4cafSjsing * the apps directory (application code) you must include an acknowledgement:
39e90e4cafSjsing * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40e90e4cafSjsing *
41e90e4cafSjsing * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42e90e4cafSjsing * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43e90e4cafSjsing * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44e90e4cafSjsing * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45e90e4cafSjsing * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46e90e4cafSjsing * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47e90e4cafSjsing * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48e90e4cafSjsing * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49e90e4cafSjsing * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50e90e4cafSjsing * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51e90e4cafSjsing * SUCH DAMAGE.
52e90e4cafSjsing *
53e90e4cafSjsing * The licence and distribution terms for any publically available version or
54e90e4cafSjsing * derivative of this code cannot be changed. i.e. this code cannot simply be
55e90e4cafSjsing * copied and put under another distribution licence
56e90e4cafSjsing * [including the GNU Public Licence.]
57e90e4cafSjsing */
58e90e4cafSjsing /* ====================================================================
59e90e4cafSjsing * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
60e90e4cafSjsing *
61e90e4cafSjsing * Redistribution and use in source and binary forms, with or without
62e90e4cafSjsing * modification, are permitted provided that the following conditions
63e90e4cafSjsing * are met:
64e90e4cafSjsing *
65e90e4cafSjsing * 1. Redistributions of source code must retain the above copyright
66e90e4cafSjsing * notice, this list of conditions and the following disclaimer.
67e90e4cafSjsing *
68e90e4cafSjsing * 2. Redistributions in binary form must reproduce the above copyright
69e90e4cafSjsing * notice, this list of conditions and the following disclaimer in
70e90e4cafSjsing * the documentation and/or other materials provided with the
71e90e4cafSjsing * distribution.
72e90e4cafSjsing *
73e90e4cafSjsing * 3. All advertising materials mentioning features or use of this
74e90e4cafSjsing * software must display the following acknowledgment:
75e90e4cafSjsing * "This product includes software developed by the OpenSSL Project
76e90e4cafSjsing * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77e90e4cafSjsing *
78e90e4cafSjsing * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79e90e4cafSjsing * endorse or promote products derived from this software without
80e90e4cafSjsing * prior written permission. For written permission, please contact
81e90e4cafSjsing * openssl-core@openssl.org.
82e90e4cafSjsing *
83e90e4cafSjsing * 5. Products derived from this software may not be called "OpenSSL"
84e90e4cafSjsing * nor may "OpenSSL" appear in their names without prior written
85e90e4cafSjsing * permission of the OpenSSL Project.
86e90e4cafSjsing *
87e90e4cafSjsing * 6. Redistributions of any form whatsoever must retain the following
88e90e4cafSjsing * acknowledgment:
89e90e4cafSjsing * "This product includes software developed by the OpenSSL Project
90e90e4cafSjsing * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91e90e4cafSjsing *
92e90e4cafSjsing * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93e90e4cafSjsing * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94e90e4cafSjsing * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95e90e4cafSjsing * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
96e90e4cafSjsing * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97e90e4cafSjsing * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98e90e4cafSjsing * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99e90e4cafSjsing * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100e90e4cafSjsing * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101e90e4cafSjsing * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102e90e4cafSjsing * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103e90e4cafSjsing * OF THE POSSIBILITY OF SUCH DAMAGE.
104e90e4cafSjsing * ====================================================================
105e90e4cafSjsing *
106e90e4cafSjsing * This product includes cryptographic software written by Eric Young
107e90e4cafSjsing * (eay@cryptsoft.com). This product includes software written by Tim
108e90e4cafSjsing * Hudson (tjh@cryptsoft.com).
109e90e4cafSjsing *
110e90e4cafSjsing */
111e90e4cafSjsing /* ====================================================================
112e90e4cafSjsing * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
113e90e4cafSjsing * ECC cipher suite support in OpenSSL originally developed by
114e90e4cafSjsing * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
115e90e4cafSjsing */
116e90e4cafSjsing /* ====================================================================
117e90e4cafSjsing * Copyright 2005 Nokia. All rights reserved.
118e90e4cafSjsing *
119e90e4cafSjsing * The portions of the attached software ("Contribution") is developed by
120e90e4cafSjsing * Nokia Corporation and is licensed pursuant to the OpenSSL open source
121e90e4cafSjsing * license.
122e90e4cafSjsing *
123e90e4cafSjsing * The Contribution, originally written by Mika Kousa and Pasi Eronen of
124e90e4cafSjsing * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
125e90e4cafSjsing * support (see RFC 4279) to OpenSSL.
126e90e4cafSjsing *
127e90e4cafSjsing * No patent licenses or other rights except those expressly stated in
128e90e4cafSjsing * the OpenSSL open source license shall be deemed granted or received
129e90e4cafSjsing * expressly, by implication, estoppel, or otherwise.
130e90e4cafSjsing *
131e90e4cafSjsing * No assurances are provided by Nokia that the Contribution does not
132e90e4cafSjsing * infringe the patent or other intellectual property rights of any third
133e90e4cafSjsing * party or that the license provides you with all the necessary rights
134e90e4cafSjsing * to make use of the Contribution.
135e90e4cafSjsing *
136e90e4cafSjsing * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
137e90e4cafSjsing * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
138e90e4cafSjsing * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
139e90e4cafSjsing * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
140e90e4cafSjsing * OTHERWISE.
141e90e4cafSjsing */
142e90e4cafSjsing
1432287d13aStb /* XXX - USE_BIOPAIR code needs updating for BIO_n{read,write}{,0} removal. */
1442287d13aStb /* #define USE_BIOPAIR */
1452287d13aStb
146e90e4cafSjsing #define _BSD_SOURCE 1 /* Or gethostname won't be declared properly
147e90e4cafSjsing on Linux and GNU platforms. */
148e90e4cafSjsing #include <sys/types.h>
149e90e4cafSjsing #include <sys/socket.h>
150e90e4cafSjsing
151e90e4cafSjsing #include <netinet/in.h>
152e90e4cafSjsing
153e90e4cafSjsing #include <assert.h>
154e90e4cafSjsing #include <errno.h>
155e90e4cafSjsing #include <limits.h>
156e90e4cafSjsing #include <netdb.h>
157e90e4cafSjsing #include <stdio.h>
158e90e4cafSjsing #include <stdlib.h>
159e90e4cafSjsing #include <string.h>
160e90e4cafSjsing #include <time.h>
161e90e4cafSjsing #include <unistd.h>
162e90e4cafSjsing
163e90e4cafSjsing #include <openssl/opensslconf.h>
164e90e4cafSjsing #include <openssl/bio.h>
165e90e4cafSjsing #include <openssl/crypto.h>
166e90e4cafSjsing #include <openssl/evp.h>
167e90e4cafSjsing #include <openssl/x509.h>
168e90e4cafSjsing #include <openssl/x509v3.h>
169e90e4cafSjsing #include <openssl/ssl.h>
170e90e4cafSjsing #include <openssl/err.h>
171e90e4cafSjsing #include <openssl/rand.h>
172e90e4cafSjsing #include <openssl/rsa.h>
173e90e4cafSjsing #include <openssl/dsa.h>
174e90e4cafSjsing #include <openssl/dh.h>
175e90e4cafSjsing #include <openssl/bn.h>
176e90e4cafSjsing
177c9675a23Stb #include "ssl_local.h"
178b3b86eecSjsing
179e90e4cafSjsing #define TEST_SERVER_CERT "../apps/server.pem"
180e90e4cafSjsing #define TEST_CLIENT_CERT "../apps/client.pem"
181e90e4cafSjsing
182e90e4cafSjsing static int verify_callback(int ok, X509_STORE_CTX *ctx);
183e90e4cafSjsing static int app_verify_callback(X509_STORE_CTX *ctx, void *arg);
184e90e4cafSjsing
185e90e4cafSjsing static DH *get_dh1024(void);
186e90e4cafSjsing static DH *get_dh1024dsa(void);
187e90e4cafSjsing
188e90e4cafSjsing static BIO *bio_err = NULL;
189e90e4cafSjsing static BIO *bio_stdout = NULL;
190e90e4cafSjsing
19100422117Sjsing static const char *alpn_client;
19200422117Sjsing static const char *alpn_server;
19300422117Sjsing static const char *alpn_expected;
19400422117Sjsing static unsigned char *alpn_selected;
19500422117Sjsing
19600422117Sjsing /*
19700422117Sjsing * next_protos_parse parses a comma separated list of strings into a string
19800422117Sjsing * in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
19900422117Sjsing * outlen: (output) set to the length of the resulting buffer on success.
20000422117Sjsing * err: (maybe NULL) on failure, an error message line is written to this BIO.
20100422117Sjsing * in: a NUL terminated string like "abc,def,ghi"
20200422117Sjsing *
20300422117Sjsing * returns: a malloced buffer or NULL on failure.
20400422117Sjsing */
20500422117Sjsing static unsigned char *
next_protos_parse(unsigned short * outlen,const char * in)20600422117Sjsing next_protos_parse(unsigned short *outlen, const char *in)
20700422117Sjsing {
20800422117Sjsing size_t i, len, start = 0;
20900422117Sjsing unsigned char *out;
21000422117Sjsing
21100422117Sjsing len = strlen(in);
21200422117Sjsing if (len >= 65535)
21300422117Sjsing return (NULL);
21400422117Sjsing
21500422117Sjsing if ((out = malloc(strlen(in) + 1)) == NULL)
21600422117Sjsing return (NULL);
21700422117Sjsing
21800422117Sjsing for (i = 0; i <= len; ++i) {
21900422117Sjsing if (i == len || in[i] == ',') {
22000422117Sjsing if (i - start > 255) {
22100422117Sjsing free(out);
22200422117Sjsing return (NULL);
22300422117Sjsing }
22400422117Sjsing out[start] = i - start;
22500422117Sjsing start = i + 1;
22600422117Sjsing } else
22700422117Sjsing out[i+1] = in[i];
22800422117Sjsing }
22900422117Sjsing *outlen = len + 1;
23000422117Sjsing return (out);
23100422117Sjsing }
23200422117Sjsing
23300422117Sjsing static int
cb_server_alpn(SSL * s,const unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen,void * arg)23400422117Sjsing cb_server_alpn(SSL *s, const unsigned char **out, unsigned char *outlen,
23500422117Sjsing const unsigned char *in, unsigned int inlen, void *arg)
23600422117Sjsing {
23700422117Sjsing unsigned char *protos;
23800422117Sjsing unsigned short protos_len;
23900422117Sjsing
24000422117Sjsing if ((protos = next_protos_parse(&protos_len, alpn_server)) == NULL) {
24100422117Sjsing fprintf(stderr,
24200422117Sjsing "failed to parser ALPN server protocol string: %s\n",
24300422117Sjsing alpn_server);
24400422117Sjsing abort();
24500422117Sjsing }
24600422117Sjsing
24700422117Sjsing if (SSL_select_next_proto((unsigned char **)out, outlen, protos,
24800422117Sjsing protos_len, in, inlen) != OPENSSL_NPN_NEGOTIATED) {
24900422117Sjsing free(protos);
25000422117Sjsing return (SSL_TLSEXT_ERR_NOACK);
25100422117Sjsing }
25200422117Sjsing
25300422117Sjsing /*
25400422117Sjsing * Make a copy of the selected protocol which will be freed in
25500422117Sjsing * verify_alpn.
25600422117Sjsing */
257df6ddd9bStb free(alpn_selected);
25800422117Sjsing if ((alpn_selected = malloc(*outlen)) == NULL) {
25900422117Sjsing fprintf(stderr, "malloc failed\n");
26000422117Sjsing abort();
26100422117Sjsing }
26200422117Sjsing memcpy(alpn_selected, *out, *outlen);
26300422117Sjsing *out = alpn_selected;
26400422117Sjsing free(protos);
26500422117Sjsing
26600422117Sjsing return (SSL_TLSEXT_ERR_OK);
26700422117Sjsing }
26800422117Sjsing
26900422117Sjsing static int
verify_alpn(SSL * client,SSL * server)27000422117Sjsing verify_alpn(SSL *client, SSL *server)
27100422117Sjsing {
27200422117Sjsing const unsigned char *client_proto, *server_proto;
27300422117Sjsing unsigned int client_proto_len = 0, server_proto_len = 0;
27400422117Sjsing
27500422117Sjsing SSL_get0_alpn_selected(client, &client_proto, &client_proto_len);
27600422117Sjsing SSL_get0_alpn_selected(server, &server_proto, &server_proto_len);
27700422117Sjsing
27800422117Sjsing free(alpn_selected);
27900422117Sjsing alpn_selected = NULL;
28000422117Sjsing
2813220613cStb if (client_proto_len != server_proto_len || (client_proto_len > 0 &&
2823220613cStb memcmp(client_proto, server_proto, client_proto_len) != 0)) {
28300422117Sjsing BIO_printf(bio_stdout, "ALPN selected protocols differ!\n");
28400422117Sjsing goto err;
28500422117Sjsing }
28600422117Sjsing
28700422117Sjsing if (client_proto_len > 0 && alpn_expected == NULL) {
28800422117Sjsing BIO_printf(bio_stdout, "ALPN unexpectedly negotiated\n");
28900422117Sjsing goto err;
29000422117Sjsing }
29100422117Sjsing
29200422117Sjsing if (alpn_expected != NULL &&
29300422117Sjsing (client_proto_len != strlen(alpn_expected) ||
29400422117Sjsing memcmp(client_proto, alpn_expected, client_proto_len) != 0)) {
29500422117Sjsing BIO_printf(bio_stdout, "ALPN selected protocols not equal to "
29600422117Sjsing "expected protocol: %s\n", alpn_expected);
29700422117Sjsing goto err;
29800422117Sjsing }
29900422117Sjsing
30000422117Sjsing return (0);
30100422117Sjsing
30200422117Sjsing err:
30300422117Sjsing BIO_printf(bio_stdout, "ALPN results: client: '");
30400422117Sjsing BIO_write(bio_stdout, client_proto, client_proto_len);
30500422117Sjsing BIO_printf(bio_stdout, "', server: '");
30600422117Sjsing BIO_write(bio_stdout, server_proto, server_proto_len);
30700422117Sjsing BIO_printf(bio_stdout, "'\n");
30800422117Sjsing BIO_printf(bio_stdout, "ALPN configured: client: '%s', server: '%s'\n",
30900422117Sjsing alpn_client, alpn_server);
31000422117Sjsing
31100422117Sjsing return (-1);
31200422117Sjsing }
31300422117Sjsing
314e90e4cafSjsing static char *cipher = NULL;
315e90e4cafSjsing static int verbose = 0;
316e90e4cafSjsing static int debug = 0;
317e90e4cafSjsing
3181b38a69bSjsing int doit_biopair(SSL *s_ssl, SSL *c_ssl, long bytes, clock_t *s_time,
3191b38a69bSjsing clock_t *c_time);
320e90e4cafSjsing int doit(SSL *s_ssl, SSL *c_ssl, long bytes);
321bb4517aeSjsing
322e90e4cafSjsing static void
sv_usage(void)323e90e4cafSjsing sv_usage(void)
324e90e4cafSjsing {
325e90e4cafSjsing fprintf(stderr, "usage: ssltest [args ...]\n");
326e90e4cafSjsing fprintf(stderr, "\n");
327e90e4cafSjsing fprintf(stderr, " -server_auth - check server certificate\n");
328e90e4cafSjsing fprintf(stderr, " -client_auth - do client authentication\n");
329e90e4cafSjsing fprintf(stderr, " -proxy - allow proxy certificates\n");
330e90e4cafSjsing fprintf(stderr, " -proxy_auth <val> - set proxy policy rights\n");
331e90e4cafSjsing fprintf(stderr, " -proxy_cond <val> - experssion to test proxy policy rights\n");
332e90e4cafSjsing fprintf(stderr, " -v - more output\n");
333e90e4cafSjsing fprintf(stderr, " -d - debug output\n");
334e90e4cafSjsing fprintf(stderr, " -reuse - use session-id reuse\n");
335e90e4cafSjsing fprintf(stderr, " -num <val> - number of connections to perform\n");
336e90e4cafSjsing fprintf(stderr, " -bytes <val> - number of bytes to swap between client/server\n");
337e90e4cafSjsing fprintf(stderr, " -dhe1024dsa - use 1024 bit key (with 160-bit subprime) for DHE\n");
338e90e4cafSjsing fprintf(stderr, " -no_dhe - disable DHE\n");
339e90e4cafSjsing fprintf(stderr, " -no_ecdhe - disable ECDHE\n");
340521ba2f2Sbeck fprintf(stderr, " -dtls1_2 - use DTLSv1.2\n");
341e90e4cafSjsing fprintf(stderr, " -tls1 - use TLSv1\n");
34217e2d200Sjsing fprintf(stderr, " -tls1_2 - use TLSv1.2\n");
343e90e4cafSjsing fprintf(stderr, " -CApath arg - PEM format directory of CA's\n");
344e90e4cafSjsing fprintf(stderr, " -CAfile arg - PEM format file of CA's\n");
345e90e4cafSjsing fprintf(stderr, " -cert arg - Server certificate file\n");
346e90e4cafSjsing fprintf(stderr, " -key arg - Server key file (default: same as -cert)\n");
347e90e4cafSjsing fprintf(stderr, " -c_cert arg - Client certificate file\n");
348e90e4cafSjsing fprintf(stderr, " -c_key arg - Client key file (default: same as -c_cert)\n");
349e90e4cafSjsing fprintf(stderr, " -cipher arg - The cipher list\n");
350e90e4cafSjsing fprintf(stderr, " -bio_pair - Use BIO pairs\n");
351e90e4cafSjsing fprintf(stderr, " -f - Test even cases that can't work\n");
352e90e4cafSjsing fprintf(stderr, " -time - measure processor time used by client and server\n");
353e90e4cafSjsing fprintf(stderr, " -named_curve arg - Elliptic curve name to use for ephemeral ECDH keys.\n" \
354e90e4cafSjsing " Use \"openssl ecparam -list_curves\" for all names\n" \
355e90e4cafSjsing " (default is sect163r2).\n");
35600422117Sjsing fprintf(stderr, " -alpn_client <string> - have client side offer ALPN\n");
35700422117Sjsing fprintf(stderr, " -alpn_server <string> - have server side offer ALPN\n");
35800422117Sjsing fprintf(stderr, " -alpn_expected <string> - the ALPN protocol that should be negotiated\n");
359e90e4cafSjsing }
360e90e4cafSjsing
361e90e4cafSjsing static void
print_details(SSL * c_ssl,const char * prefix)362e90e4cafSjsing print_details(SSL *c_ssl, const char *prefix)
363e90e4cafSjsing {
364e90e4cafSjsing const SSL_CIPHER *ciph;
36578191710Stb X509 *cert = NULL;
36678191710Stb EVP_PKEY *pkey;
367e90e4cafSjsing
368e90e4cafSjsing ciph = SSL_get_current_cipher(c_ssl);
369e90e4cafSjsing BIO_printf(bio_stdout, "%s%s, cipher %s %s",
3701b38a69bSjsing prefix, SSL_get_version(c_ssl), SSL_CIPHER_get_version(ciph),
371e90e4cafSjsing SSL_CIPHER_get_name(ciph));
37278191710Stb
37378191710Stb if ((cert = SSL_get_peer_certificate(c_ssl)) == NULL)
37478191710Stb goto out;
37578191710Stb if ((pkey = X509_get0_pubkey(cert)) == NULL)
37678191710Stb goto out;
37778191710Stb if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
37878191710Stb RSA *rsa;
37978191710Stb
38078191710Stb if ((rsa = EVP_PKEY_get0_RSA(pkey)) == NULL)
38178191710Stb goto out;
38278191710Stb
38378191710Stb BIO_printf(bio_stdout, ", %d bit RSA", RSA_bits(rsa));
38478191710Stb } else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) {
38578191710Stb DSA *dsa;
38678191710Stb const BIGNUM *p;
38778191710Stb
38878191710Stb if ((dsa = EVP_PKEY_get0_DSA(pkey)) == NULL)
38978191710Stb goto out;
39078191710Stb
39178191710Stb DSA_get0_pqg(dsa, &p, NULL, NULL);
39278191710Stb
39378191710Stb BIO_printf(bio_stdout, ", %d bit DSA", BN_num_bits(p));
394e90e4cafSjsing }
39578191710Stb
39678191710Stb out:
39778191710Stb /*
39878191710Stb * The SSL API does not allow us to look at temporary RSA/DH keys,
39978191710Stb * otherwise we should print their lengths too
40078191710Stb */
401e90e4cafSjsing BIO_printf(bio_stdout, "\n");
40278191710Stb
40378191710Stb X509_free(cert);
404e90e4cafSjsing }
405e90e4cafSjsing
406e90e4cafSjsing int
main(int argc,char * argv[])407e90e4cafSjsing main(int argc, char *argv[])
408e90e4cafSjsing {
409e90e4cafSjsing char *CApath = NULL, *CAfile = NULL;
410e90e4cafSjsing int badop = 0;
411e90e4cafSjsing int bio_pair = 0;
412e90e4cafSjsing int force = 0;
413521ba2f2Sbeck int tls1 = 0, tls1_2 = 0, dtls1_2 = 0, ret = 1;
414e90e4cafSjsing int client_auth = 0;
415e90e4cafSjsing int server_auth = 0, i;
416664ea9f8Stb char *app_verify_arg = "Test Callback Argument";
417e90e4cafSjsing char *server_cert = TEST_SERVER_CERT;
418e90e4cafSjsing char *server_key = NULL;
419e90e4cafSjsing char *client_cert = TEST_CLIENT_CERT;
420e90e4cafSjsing char *client_key = NULL;
421e90e4cafSjsing char *named_curve = NULL;
422e90e4cafSjsing SSL_CTX *s_ctx = NULL;
423e90e4cafSjsing SSL_CTX *c_ctx = NULL;
424e90e4cafSjsing const SSL_METHOD *meth = NULL;
425e90e4cafSjsing SSL *c_ssl, *s_ssl;
426e90e4cafSjsing int number = 1, reuse = 0;
427517f1d0fStb int seclevel = 0;
428e90e4cafSjsing long bytes = 256L;
429e90e4cafSjsing DH *dh;
430855052a0Smiod int dhe1024dsa = 0;
431e90e4cafSjsing EC_KEY *ecdh = NULL;
432e90e4cafSjsing int no_dhe = 0;
433e90e4cafSjsing int no_ecdhe = 0;
434e90e4cafSjsing int print_time = 0;
435e90e4cafSjsing clock_t s_time = 0, c_time = 0;
436e90e4cafSjsing
437e90e4cafSjsing verbose = 0;
438e90e4cafSjsing debug = 0;
439e90e4cafSjsing cipher = 0;
440e90e4cafSjsing
441e90e4cafSjsing bio_err = BIO_new_fp(stderr, BIO_NOCLOSE|BIO_FP_TEXT);
442e90e4cafSjsing
443e90e4cafSjsing bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE|BIO_FP_TEXT);
444e90e4cafSjsing
445e90e4cafSjsing argc--;
446e90e4cafSjsing argv++;
447e90e4cafSjsing
448e90e4cafSjsing while (argc >= 1) {
449e90e4cafSjsing if (!strcmp(*argv, "-F")) {
450e4c7564cStb fprintf(stderr, "not compiled with FIPS support, so exiting without running.\n");
451e90e4cafSjsing exit(0);
452e90e4cafSjsing } else if (strcmp(*argv, "-server_auth") == 0)
453e90e4cafSjsing server_auth = 1;
454e90e4cafSjsing else if (strcmp(*argv, "-client_auth") == 0)
455e90e4cafSjsing client_auth = 1;
456664ea9f8Stb else if (strcmp(*argv, "-v") == 0)
457e90e4cafSjsing verbose = 1;
458e90e4cafSjsing else if (strcmp(*argv, "-d") == 0)
459e90e4cafSjsing debug = 1;
460e90e4cafSjsing else if (strcmp(*argv, "-reuse") == 0)
461e90e4cafSjsing reuse = 1;
462855052a0Smiod else if (strcmp(*argv, "-dhe1024dsa") == 0) {
463e90e4cafSjsing dhe1024dsa = 1;
464e90e4cafSjsing } else if (strcmp(*argv, "-no_dhe") == 0)
465e90e4cafSjsing no_dhe = 1;
466e90e4cafSjsing else if (strcmp(*argv, "-no_ecdhe") == 0)
467e90e4cafSjsing no_ecdhe = 1;
468521ba2f2Sbeck else if (strcmp(*argv, "-dtls1_2") == 0)
469521ba2f2Sbeck dtls1_2 = 1;
470c419fba1Sjsing else if (strcmp(*argv, "-tls1") == 0)
471c419fba1Sjsing tls1 = 1;
47217e2d200Sjsing else if (strcmp(*argv, "-tls1_2") == 0)
47317e2d200Sjsing tls1_2 = 1;
474e90e4cafSjsing else if (strncmp(*argv, "-num", 4) == 0) {
475e90e4cafSjsing if (--argc < 1)
476e90e4cafSjsing goto bad;
477e90e4cafSjsing number = atoi(*(++argv));
478e90e4cafSjsing if (number == 0)
479e90e4cafSjsing number = 1;
480517f1d0fStb } else if (strncmp(*argv, "-seclevel", 9) == 0) {
481517f1d0fStb if (--argc < 1)
482517f1d0fStb goto bad;
483517f1d0fStb seclevel = atoi(*(++argv));
484e90e4cafSjsing } else if (strcmp(*argv, "-bytes") == 0) {
485e90e4cafSjsing if (--argc < 1)
486e90e4cafSjsing goto bad;
487e90e4cafSjsing bytes = atol(*(++argv));
488e90e4cafSjsing if (bytes == 0L)
489e90e4cafSjsing bytes = 1L;
490e90e4cafSjsing i = strlen(argv[0]);
491e90e4cafSjsing if (argv[0][i - 1] == 'k')
492e90e4cafSjsing bytes*=1024L;
493e90e4cafSjsing if (argv[0][i - 1] == 'm')
494e90e4cafSjsing bytes*=1024L*1024L;
495e90e4cafSjsing } else if (strcmp(*argv, "-cert") == 0) {
496e90e4cafSjsing if (--argc < 1)
497e90e4cafSjsing goto bad;
498e90e4cafSjsing server_cert= *(++argv);
499e90e4cafSjsing } else if (strcmp(*argv, "-s_cert") == 0) {
500e90e4cafSjsing if (--argc < 1)
501e90e4cafSjsing goto bad;
502e90e4cafSjsing server_cert= *(++argv);
503e90e4cafSjsing } else if (strcmp(*argv, "-key") == 0) {
504e90e4cafSjsing if (--argc < 1)
505e90e4cafSjsing goto bad;
506e90e4cafSjsing server_key= *(++argv);
507e90e4cafSjsing } else if (strcmp(*argv, "-s_key") == 0) {
508e90e4cafSjsing if (--argc < 1)
509e90e4cafSjsing goto bad;
510e90e4cafSjsing server_key= *(++argv);
511e90e4cafSjsing } else if (strcmp(*argv, "-c_cert") == 0) {
512e90e4cafSjsing if (--argc < 1)
513e90e4cafSjsing goto bad;
514e90e4cafSjsing client_cert= *(++argv);
515e90e4cafSjsing } else if (strcmp(*argv, "-c_key") == 0) {
516e90e4cafSjsing if (--argc < 1)
517e90e4cafSjsing goto bad;
518e90e4cafSjsing client_key= *(++argv);
519e90e4cafSjsing } else if (strcmp(*argv, "-cipher") == 0) {
520e90e4cafSjsing if (--argc < 1)
521e90e4cafSjsing goto bad;
522e90e4cafSjsing cipher= *(++argv);
523e90e4cafSjsing } else if (strcmp(*argv, "-CApath") == 0) {
524e90e4cafSjsing if (--argc < 1)
525e90e4cafSjsing goto bad;
526e90e4cafSjsing CApath= *(++argv);
527e90e4cafSjsing } else if (strcmp(*argv, "-CAfile") == 0) {
528e90e4cafSjsing if (--argc < 1)
529e90e4cafSjsing goto bad;
530e90e4cafSjsing CAfile= *(++argv);
531e90e4cafSjsing } else if (strcmp(*argv, "-bio_pair") == 0) {
532e90e4cafSjsing bio_pair = 1;
533e90e4cafSjsing } else if (strcmp(*argv, "-f") == 0) {
534e90e4cafSjsing force = 1;
535e90e4cafSjsing } else if (strcmp(*argv, "-time") == 0) {
536e90e4cafSjsing print_time = 1;
537e90e4cafSjsing } else if (strcmp(*argv, "-named_curve") == 0) {
538e90e4cafSjsing if (--argc < 1)
539e90e4cafSjsing goto bad;
540e90e4cafSjsing named_curve = *(++argv);
541e90e4cafSjsing } else if (strcmp(*argv, "-app_verify") == 0) {
542664ea9f8Stb ;
54306acd9fcSjsing } else if (strcmp(*argv, "-alpn_client") == 0) {
54400422117Sjsing if (--argc < 1)
54500422117Sjsing goto bad;
54600422117Sjsing alpn_client = *(++argv);
54700422117Sjsing } else if (strcmp(*argv, "-alpn_server") == 0) {
54800422117Sjsing if (--argc < 1)
54900422117Sjsing goto bad;
55000422117Sjsing alpn_server = *(++argv);
55100422117Sjsing } else if (strcmp(*argv, "-alpn_expected") == 0) {
55200422117Sjsing if (--argc < 1)
55300422117Sjsing goto bad;
55400422117Sjsing alpn_expected = *(++argv);
55500422117Sjsing } else {
556e90e4cafSjsing fprintf(stderr, "unknown option %s\n", *argv);
557e90e4cafSjsing badop = 1;
558e90e4cafSjsing break;
559e90e4cafSjsing }
560e90e4cafSjsing argc--;
561e90e4cafSjsing argv++;
562e90e4cafSjsing }
563e90e4cafSjsing if (badop) {
564e90e4cafSjsing bad:
565e90e4cafSjsing sv_usage();
566e90e4cafSjsing goto end;
567e90e4cafSjsing }
568e90e4cafSjsing
569521ba2f2Sbeck if (!dtls1_2 && !tls1 && !tls1_2 && number > 1 && !reuse && !force) {
570e90e4cafSjsing fprintf(stderr,
571e90e4cafSjsing "This case cannot work. Use -f to perform "
572e90e4cafSjsing "the test anyway (and\n-d to see what happens), "
57317e2d200Sjsing "or add one of -dtls1, -tls1, -tls1_2, -reuse\n"
574e90e4cafSjsing "to avoid protocol mismatch.\n");
575e90e4cafSjsing exit(1);
576e90e4cafSjsing }
577e90e4cafSjsing
578e90e4cafSjsing if (print_time) {
579e90e4cafSjsing if (!bio_pair) {
580e90e4cafSjsing fprintf(stderr, "Using BIO pair (-bio_pair)\n");
581e90e4cafSjsing bio_pair = 1;
582e90e4cafSjsing }
583e90e4cafSjsing if (number < 50 && !force)
584e90e4cafSjsing fprintf(stderr, "Warning: For accurate timings, use more connections (e.g. -num 1000)\n");
585e90e4cafSjsing }
586e90e4cafSjsing
587e90e4cafSjsing /* if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */
588e90e4cafSjsing
589e90e4cafSjsing SSL_library_init();
590e90e4cafSjsing SSL_load_error_strings();
591e90e4cafSjsing
592521ba2f2Sbeck if (dtls1_2)
593521ba2f2Sbeck meth = DTLSv1_2_method();
594c419fba1Sjsing else if (tls1)
595e90e4cafSjsing meth = TLSv1_method();
59617e2d200Sjsing else if (tls1_2)
59717e2d200Sjsing meth = TLSv1_2_method();
598e90e4cafSjsing else
59917e2d200Sjsing meth = TLS_method();
600e90e4cafSjsing
601e90e4cafSjsing c_ctx = SSL_CTX_new(meth);
602e90e4cafSjsing s_ctx = SSL_CTX_new(meth);
603e90e4cafSjsing if ((c_ctx == NULL) || (s_ctx == NULL)) {
604e90e4cafSjsing ERR_print_errors(bio_err);
605e90e4cafSjsing goto end;
606e90e4cafSjsing }
607e90e4cafSjsing
608517f1d0fStb SSL_CTX_set_security_level(c_ctx, seclevel);
609517f1d0fStb SSL_CTX_set_security_level(s_ctx, seclevel);
610517f1d0fStb
611e90e4cafSjsing if (cipher != NULL) {
612e90e4cafSjsing SSL_CTX_set_cipher_list(c_ctx, cipher);
613e90e4cafSjsing SSL_CTX_set_cipher_list(s_ctx, cipher);
614e90e4cafSjsing }
615e90e4cafSjsing
616e90e4cafSjsing if (!no_dhe) {
617e90e4cafSjsing if (dhe1024dsa) {
618e90e4cafSjsing /* use SSL_OP_SINGLE_DH_USE to avoid small subgroup attacks */
619e90e4cafSjsing SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE);
620e90e4cafSjsing dh = get_dh1024dsa();
621855052a0Smiod } else
622e90e4cafSjsing dh = get_dh1024();
623e90e4cafSjsing SSL_CTX_set_tmp_dh(s_ctx, dh);
624e90e4cafSjsing DH_free(dh);
625e90e4cafSjsing }
626e90e4cafSjsing
627e90e4cafSjsing if (!no_ecdhe) {
628e90e4cafSjsing int nid;
629e90e4cafSjsing
630e90e4cafSjsing if (named_curve != NULL) {
631e90e4cafSjsing nid = OBJ_sn2nid(named_curve);
632e90e4cafSjsing if (nid == 0) {
633e90e4cafSjsing BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve);
634e90e4cafSjsing goto end;
635e90e4cafSjsing }
636e90e4cafSjsing } else
637e90e4cafSjsing nid = NID_X9_62_prime256v1;
638e90e4cafSjsing
639e90e4cafSjsing ecdh = EC_KEY_new_by_curve_name(nid);
640e90e4cafSjsing if (ecdh == NULL) {
641e90e4cafSjsing BIO_printf(bio_err, "unable to create curve\n");
642e90e4cafSjsing goto end;
643e90e4cafSjsing }
644e90e4cafSjsing
645e90e4cafSjsing SSL_CTX_set_tmp_ecdh(s_ctx, ecdh);
646e90e4cafSjsing SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_ECDH_USE);
647e90e4cafSjsing EC_KEY_free(ecdh);
648e90e4cafSjsing }
649e90e4cafSjsing
65057499507Stb if (!SSL_CTX_use_certificate_chain_file(s_ctx, server_cert)) {
651e90e4cafSjsing ERR_print_errors(bio_err);
652e90e4cafSjsing } else if (!SSL_CTX_use_PrivateKey_file(s_ctx,
653e90e4cafSjsing (server_key ? server_key : server_cert), SSL_FILETYPE_PEM)) {
654e90e4cafSjsing ERR_print_errors(bio_err);
655e90e4cafSjsing goto end;
656e90e4cafSjsing }
657e90e4cafSjsing
658e90e4cafSjsing if (client_auth) {
65957499507Stb SSL_CTX_use_certificate_chain_file(c_ctx, client_cert);
660e90e4cafSjsing SSL_CTX_use_PrivateKey_file(c_ctx,
661e90e4cafSjsing (client_key ? client_key : client_cert),
662e90e4cafSjsing SSL_FILETYPE_PEM);
663e90e4cafSjsing }
664e90e4cafSjsing
665e90e4cafSjsing if ((!SSL_CTX_load_verify_locations(s_ctx, CAfile, CApath)) ||
666e90e4cafSjsing (!SSL_CTX_set_default_verify_paths(s_ctx)) ||
667e90e4cafSjsing (!SSL_CTX_load_verify_locations(c_ctx, CAfile, CApath)) ||
668e90e4cafSjsing (!SSL_CTX_set_default_verify_paths(c_ctx))) {
669e90e4cafSjsing /* fprintf(stderr,"SSL_load_verify_locations\n"); */
670e90e4cafSjsing ERR_print_errors(bio_err);
671e90e4cafSjsing /* goto end; */
672e90e4cafSjsing }
673e90e4cafSjsing
674e90e4cafSjsing if (client_auth) {
675e90e4cafSjsing BIO_printf(bio_err, "client authentication\n");
676e90e4cafSjsing SSL_CTX_set_verify(s_ctx,
677e90e4cafSjsing SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
678e90e4cafSjsing verify_callback);
6791b38a69bSjsing SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback,
680664ea9f8Stb app_verify_arg);
681e90e4cafSjsing }
682e90e4cafSjsing if (server_auth) {
683e90e4cafSjsing BIO_printf(bio_err, "server authentication\n");
684e90e4cafSjsing SSL_CTX_set_verify(c_ctx, SSL_VERIFY_PEER,
685e90e4cafSjsing verify_callback);
6861b38a69bSjsing SSL_CTX_set_cert_verify_callback(c_ctx, app_verify_callback,
687664ea9f8Stb app_verify_arg);
688e90e4cafSjsing }
689e90e4cafSjsing
690e90e4cafSjsing {
691e90e4cafSjsing int session_id_context = 0;
6921b38a69bSjsing SSL_CTX_set_session_id_context(s_ctx,
6931b38a69bSjsing (void *)&session_id_context, sizeof(session_id_context));
694e90e4cafSjsing }
695e90e4cafSjsing
69600422117Sjsing if (alpn_server != NULL)
69700422117Sjsing SSL_CTX_set_alpn_select_cb(s_ctx, cb_server_alpn, NULL);
69800422117Sjsing
69900422117Sjsing if (alpn_client != NULL) {
70000422117Sjsing unsigned short alpn_len;
70100422117Sjsing unsigned char *alpn = next_protos_parse(&alpn_len, alpn_client);
70200422117Sjsing
70300422117Sjsing if (alpn == NULL) {
70400422117Sjsing BIO_printf(bio_err, "Error parsing -alpn_client argument\n");
70500422117Sjsing goto end;
70600422117Sjsing }
70700422117Sjsing SSL_CTX_set_alpn_protos(c_ctx, alpn, alpn_len);
70800422117Sjsing free(alpn);
70900422117Sjsing }
71000422117Sjsing
711e90e4cafSjsing c_ssl = SSL_new(c_ctx);
712e90e4cafSjsing s_ssl = SSL_new(s_ctx);
713e90e4cafSjsing
714e90e4cafSjsing for (i = 0; i < number; i++) {
715e90e4cafSjsing if (!reuse)
716e90e4cafSjsing SSL_set_session(c_ssl, NULL);
7172287d13aStb #ifdef USE_BIOPAIR
718e90e4cafSjsing if (bio_pair)
7191b38a69bSjsing ret = doit_biopair(s_ssl, c_ssl, bytes, &s_time,
7201b38a69bSjsing &c_time);
721e90e4cafSjsing else
7222287d13aStb #endif
723e90e4cafSjsing ret = doit(s_ssl, c_ssl, bytes);
724e90e4cafSjsing }
725e90e4cafSjsing
726e90e4cafSjsing if (!verbose) {
727e90e4cafSjsing print_details(c_ssl, "");
728e90e4cafSjsing }
729e90e4cafSjsing if ((number > 1) || (bytes > 1L))
7301b38a69bSjsing BIO_printf(bio_stdout, "%d handshakes of %ld bytes done\n",
7311b38a69bSjsing number, bytes);
732e90e4cafSjsing if (print_time) {
733e90e4cafSjsing #ifdef CLOCKS_PER_SEC
734e90e4cafSjsing /* "To determine the time in seconds, the value returned
735e90e4cafSjsing * by the clock function should be divided by the value
736e90e4cafSjsing * of the macro CLOCKS_PER_SEC."
737e90e4cafSjsing * -- ISO/IEC 9899 */
7381b38a69bSjsing BIO_printf(bio_stdout,
7391b38a69bSjsing "Approximate total server time: %6.2f s\n"
740e90e4cafSjsing "Approximate total client time: %6.2f s\n",
741e90e4cafSjsing (double)s_time/CLOCKS_PER_SEC,
742e90e4cafSjsing (double)c_time/CLOCKS_PER_SEC);
743e90e4cafSjsing #else
744e90e4cafSjsing /* "`CLOCKS_PER_SEC' undeclared (first use this function)"
745e90e4cafSjsing * -- cc on NeXTstep/OpenStep */
746e90e4cafSjsing BIO_printf(bio_stdout,
747e90e4cafSjsing "Approximate total server time: %6.2f units\n"
748e90e4cafSjsing "Approximate total client time: %6.2f units\n",
749e90e4cafSjsing (double)s_time,
750e90e4cafSjsing (double)c_time);
751e90e4cafSjsing #endif
752e90e4cafSjsing }
753e90e4cafSjsing
754e90e4cafSjsing SSL_free(s_ssl);
755e90e4cafSjsing SSL_free(c_ssl);
756e90e4cafSjsing
757e90e4cafSjsing end:
758e90e4cafSjsing SSL_CTX_free(s_ctx);
759e90e4cafSjsing SSL_CTX_free(c_ctx);
760e90e4cafSjsing BIO_free(bio_stdout);
761e90e4cafSjsing
762e90e4cafSjsing CRYPTO_cleanup_all_ex_data();
763e90e4cafSjsing ERR_free_strings();
764e90e4cafSjsing ERR_remove_thread_state(NULL);
765e90e4cafSjsing EVP_cleanup();
766e90e4cafSjsing BIO_free(bio_err);
7677503bb1fSjsing
768e90e4cafSjsing exit(ret);
769e90e4cafSjsing return ret;
770e90e4cafSjsing }
771e90e4cafSjsing
7722287d13aStb #if USE_BIOPAIR
773e90e4cafSjsing int
doit_biopair(SSL * s_ssl,SSL * c_ssl,long count,clock_t * s_time,clock_t * c_time)774e90e4cafSjsing doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, clock_t *s_time,
775e90e4cafSjsing clock_t *c_time)
776e90e4cafSjsing {
777e90e4cafSjsing long cw_num = count, cr_num = count, sw_num = count, sr_num = count;
778e90e4cafSjsing BIO *s_ssl_bio = NULL, *c_ssl_bio = NULL;
7791b38a69bSjsing BIO *server = NULL, *server_io = NULL;
7801b38a69bSjsing BIO *client = NULL, *client_io = NULL;
781e90e4cafSjsing int ret = 1;
782e90e4cafSjsing
783e90e4cafSjsing size_t bufsiz = 256; /* small buffer for testing */
784e90e4cafSjsing
785e90e4cafSjsing if (!BIO_new_bio_pair(&server, bufsiz, &server_io, bufsiz))
786e90e4cafSjsing goto err;
787e90e4cafSjsing if (!BIO_new_bio_pair(&client, bufsiz, &client_io, bufsiz))
788e90e4cafSjsing goto err;
789e90e4cafSjsing
790e90e4cafSjsing s_ssl_bio = BIO_new(BIO_f_ssl());
791e90e4cafSjsing if (!s_ssl_bio)
792e90e4cafSjsing goto err;
793e90e4cafSjsing
794e90e4cafSjsing c_ssl_bio = BIO_new(BIO_f_ssl());
795e90e4cafSjsing if (!c_ssl_bio)
796e90e4cafSjsing goto err;
797e90e4cafSjsing
798e90e4cafSjsing SSL_set_connect_state(c_ssl);
799e90e4cafSjsing SSL_set_bio(c_ssl, client, client);
800e90e4cafSjsing (void)BIO_set_ssl(c_ssl_bio, c_ssl, BIO_NOCLOSE);
801e90e4cafSjsing
802e90e4cafSjsing SSL_set_accept_state(s_ssl);
803e90e4cafSjsing SSL_set_bio(s_ssl, server, server);
804e90e4cafSjsing (void)BIO_set_ssl(s_ssl_bio, s_ssl, BIO_NOCLOSE);
805e90e4cafSjsing
806e90e4cafSjsing do {
807e90e4cafSjsing /* c_ssl_bio: SSL filter BIO
808e90e4cafSjsing *
809e90e4cafSjsing * client: pseudo-I/O for SSL library
810e90e4cafSjsing *
811e90e4cafSjsing * client_io: client's SSL communication; usually to be
812e90e4cafSjsing * relayed over some I/O facility, but in this
813e90e4cafSjsing * test program, we're the server, too:
814e90e4cafSjsing *
815e90e4cafSjsing * server_io: server's SSL communication
816e90e4cafSjsing *
817e90e4cafSjsing * server: pseudo-I/O for SSL library
818e90e4cafSjsing *
819e90e4cafSjsing * s_ssl_bio: SSL filter BIO
820e90e4cafSjsing *
821e90e4cafSjsing * The client and the server each employ a "BIO pair":
822e90e4cafSjsing * client + client_io, server + server_io.
823e90e4cafSjsing * BIO pairs are symmetric. A BIO pair behaves similar
824e90e4cafSjsing * to a non-blocking socketpair (but both endpoints must
825e90e4cafSjsing * be handled by the same thread).
826e90e4cafSjsing * [Here we could connect client and server to the ends
827e90e4cafSjsing * of a single BIO pair, but then this code would be less
828e90e4cafSjsing * suitable as an example for BIO pairs in general.]
829e90e4cafSjsing *
830e90e4cafSjsing * Useful functions for querying the state of BIO pair endpoints:
831e90e4cafSjsing *
832e90e4cafSjsing * BIO_ctrl_pending(bio) number of bytes we can read now
833e90e4cafSjsing * BIO_ctrl_get_read_request(bio) number of bytes needed to fulfil
834e90e4cafSjsing * other side's read attempt
835e90e4cafSjsing * BIO_ctrl_get_write_guarantee(bio) number of bytes we can write now
836e90e4cafSjsing *
837e90e4cafSjsing * ..._read_request is never more than ..._write_guarantee;
838e90e4cafSjsing * it depends on the application which one you should use.
839e90e4cafSjsing */
840e90e4cafSjsing
841e90e4cafSjsing /* We have non-blocking behaviour throughout this test program, but
842e90e4cafSjsing * can be sure that there is *some* progress in each iteration; so
843e90e4cafSjsing * we don't have to worry about ..._SHOULD_READ or ..._SHOULD_WRITE
844e90e4cafSjsing * -- we just try everything in each iteration
845e90e4cafSjsing */
846e90e4cafSjsing
847e90e4cafSjsing {
848e90e4cafSjsing /* CLIENT */
849e90e4cafSjsing
850e90e4cafSjsing char cbuf[1024*8];
851e90e4cafSjsing int i, r;
852e90e4cafSjsing clock_t c_clock = clock();
853e90e4cafSjsing
854e90e4cafSjsing memset(cbuf, 0, sizeof(cbuf));
855e90e4cafSjsing
856e90e4cafSjsing if (debug)
857e90e4cafSjsing if (SSL_in_init(c_ssl))
858e90e4cafSjsing printf("client waiting in SSL_connect - %s\n",
859e90e4cafSjsing SSL_state_string_long(c_ssl));
860e90e4cafSjsing
861e90e4cafSjsing if (cw_num > 0) {
862e90e4cafSjsing /* Write to server. */
863e90e4cafSjsing
864e90e4cafSjsing if (cw_num > (long)sizeof cbuf)
865e90e4cafSjsing i = sizeof cbuf;
866e90e4cafSjsing else
867e90e4cafSjsing i = (int)cw_num;
868e90e4cafSjsing r = BIO_write(c_ssl_bio, cbuf, i);
869e90e4cafSjsing if (r < 0) {
870e90e4cafSjsing if (!BIO_should_retry(c_ssl_bio)) {
871e90e4cafSjsing fprintf(stderr, "ERROR in CLIENT\n");
872e90e4cafSjsing goto err;
873e90e4cafSjsing }
874e90e4cafSjsing /* BIO_should_retry(...) can just be ignored here.
875e90e4cafSjsing * The library expects us to call BIO_write with
876e90e4cafSjsing * the same arguments again, and that's what we will
877e90e4cafSjsing * do in the next iteration. */
878e90e4cafSjsing } else if (r == 0) {
879e90e4cafSjsing fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
880e90e4cafSjsing goto err;
881e90e4cafSjsing } else {
882e90e4cafSjsing if (debug)
883e90e4cafSjsing printf("client wrote %d\n", r);
884e90e4cafSjsing cw_num -= r;
885e90e4cafSjsing
886e90e4cafSjsing }
887e90e4cafSjsing }
888e90e4cafSjsing
889e90e4cafSjsing if (cr_num > 0) {
890e90e4cafSjsing /* Read from server. */
891e90e4cafSjsing
892e90e4cafSjsing r = BIO_read(c_ssl_bio, cbuf, sizeof(cbuf));
893e90e4cafSjsing if (r < 0) {
894e90e4cafSjsing if (!BIO_should_retry(c_ssl_bio)) {
895e90e4cafSjsing fprintf(stderr, "ERROR in CLIENT\n");
896e90e4cafSjsing goto err;
897e90e4cafSjsing }
898e90e4cafSjsing /* Again, "BIO_should_retry" can be ignored. */
899e90e4cafSjsing } else if (r == 0) {
900e90e4cafSjsing fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
901e90e4cafSjsing goto err;
902e90e4cafSjsing } else {
903e90e4cafSjsing if (debug)
904e90e4cafSjsing printf("client read %d\n", r);
905e90e4cafSjsing cr_num -= r;
906e90e4cafSjsing }
907e90e4cafSjsing }
908e90e4cafSjsing
909e90e4cafSjsing /* c_time and s_time increments will typically be very small
910e90e4cafSjsing * (depending on machine speed and clock tick intervals),
911e90e4cafSjsing * but sampling over a large number of connections should
912e90e4cafSjsing * result in fairly accurate figures. We cannot guarantee
913e90e4cafSjsing * a lot, however -- if each connection lasts for exactly
914e90e4cafSjsing * one clock tick, it will be counted only for the client
915e90e4cafSjsing * or only for the server or even not at all.
916e90e4cafSjsing */
917e90e4cafSjsing *c_time += (clock() - c_clock);
918e90e4cafSjsing }
919e90e4cafSjsing
920e90e4cafSjsing {
921e90e4cafSjsing /* SERVER */
922e90e4cafSjsing
923e90e4cafSjsing char sbuf[1024*8];
924e90e4cafSjsing int i, r;
925e90e4cafSjsing clock_t s_clock = clock();
926e90e4cafSjsing
927e90e4cafSjsing memset(sbuf, 0, sizeof(sbuf));
928e90e4cafSjsing
929e90e4cafSjsing if (debug)
930e90e4cafSjsing if (SSL_in_init(s_ssl))
931e90e4cafSjsing printf("server waiting in SSL_accept - %s\n",
932e90e4cafSjsing SSL_state_string_long(s_ssl));
933e90e4cafSjsing
934e90e4cafSjsing if (sw_num > 0) {
935e90e4cafSjsing /* Write to client. */
936e90e4cafSjsing
937e90e4cafSjsing if (sw_num > (long)sizeof sbuf)
938e90e4cafSjsing i = sizeof sbuf;
939e90e4cafSjsing else
940e90e4cafSjsing i = (int)sw_num;
941e90e4cafSjsing r = BIO_write(s_ssl_bio, sbuf, i);
942e90e4cafSjsing if (r < 0) {
943e90e4cafSjsing if (!BIO_should_retry(s_ssl_bio)) {
944e90e4cafSjsing fprintf(stderr, "ERROR in SERVER\n");
945e90e4cafSjsing goto err;
946e90e4cafSjsing }
947e90e4cafSjsing /* Ignore "BIO_should_retry". */
948e90e4cafSjsing } else if (r == 0) {
949e90e4cafSjsing fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
950e90e4cafSjsing goto err;
951e90e4cafSjsing } else {
952e90e4cafSjsing if (debug)
953e90e4cafSjsing printf("server wrote %d\n", r);
954e90e4cafSjsing sw_num -= r;
955e90e4cafSjsing
956e90e4cafSjsing }
957e90e4cafSjsing }
958e90e4cafSjsing
959e90e4cafSjsing if (sr_num > 0) {
960e90e4cafSjsing /* Read from client. */
961e90e4cafSjsing
962e90e4cafSjsing r = BIO_read(s_ssl_bio, sbuf, sizeof(sbuf));
963e90e4cafSjsing if (r < 0) {
964e90e4cafSjsing if (!BIO_should_retry(s_ssl_bio)) {
965e90e4cafSjsing fprintf(stderr, "ERROR in SERVER\n");
966e90e4cafSjsing goto err;
967e90e4cafSjsing }
968e90e4cafSjsing /* blah, blah */
969e90e4cafSjsing } else if (r == 0) {
970e90e4cafSjsing fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
971e90e4cafSjsing goto err;
972e90e4cafSjsing } else {
973e90e4cafSjsing if (debug)
974e90e4cafSjsing printf("server read %d\n", r);
975e90e4cafSjsing sr_num -= r;
976e90e4cafSjsing }
977e90e4cafSjsing }
978e90e4cafSjsing
979e90e4cafSjsing *s_time += (clock() - s_clock);
980e90e4cafSjsing }
981e90e4cafSjsing
982e90e4cafSjsing {
983e90e4cafSjsing /* "I/O" BETWEEN CLIENT AND SERVER. */
984e90e4cafSjsing
985e90e4cafSjsing size_t r1, r2;
986e90e4cafSjsing BIO *io1 = server_io, *io2 = client_io;
987e90e4cafSjsing /* we use the non-copying interface for io1
988e90e4cafSjsing * and the standard BIO_write/BIO_read interface for io2
989e90e4cafSjsing */
990e90e4cafSjsing
991e90e4cafSjsing static int prev_progress = 1;
992e90e4cafSjsing int progress = 0;
993e90e4cafSjsing
994e90e4cafSjsing /* io1 to io2 */
9951b38a69bSjsing do {
996e90e4cafSjsing size_t num;
997e90e4cafSjsing int r;
998e90e4cafSjsing
999e90e4cafSjsing r1 = BIO_ctrl_pending(io1);
1000e90e4cafSjsing r2 = BIO_ctrl_get_write_guarantee(io2);
1001e90e4cafSjsing
1002e90e4cafSjsing num = r1;
1003e90e4cafSjsing if (r2 < num)
1004e90e4cafSjsing num = r2;
1005e90e4cafSjsing if (num) {
1006e90e4cafSjsing char *dataptr;
1007e90e4cafSjsing
1008e90e4cafSjsing if (INT_MAX < num) /* yeah, right */
1009e90e4cafSjsing num = INT_MAX;
1010e90e4cafSjsing
1011e90e4cafSjsing r = BIO_nread(io1, &dataptr, (int)num);
1012e90e4cafSjsing assert(r > 0);
1013e90e4cafSjsing assert(r <= (int)num);
1014e90e4cafSjsing /* possibly r < num (non-contiguous data) */
1015e90e4cafSjsing num = r;
1016e90e4cafSjsing r = BIO_write(io2, dataptr, (int)num);
1017e90e4cafSjsing if (r != (int)num) /* can't happen */
1018e90e4cafSjsing {
1019e90e4cafSjsing fprintf(stderr, "ERROR: BIO_write could not write "
1020e90e4cafSjsing "BIO_ctrl_get_write_guarantee() bytes");
1021e90e4cafSjsing goto err;
1022e90e4cafSjsing }
1023e90e4cafSjsing progress = 1;
1024e90e4cafSjsing
1025e90e4cafSjsing if (debug)
1026e90e4cafSjsing printf((io1 == client_io) ?
1027e90e4cafSjsing "C->S relaying: %d bytes\n" :
1028e90e4cafSjsing "S->C relaying: %d bytes\n",
1029e90e4cafSjsing (int)num);
1030e90e4cafSjsing }
1031e90e4cafSjsing } while (r1 && r2);
1032e90e4cafSjsing
1033e90e4cafSjsing /* io2 to io1 */
1034e90e4cafSjsing {
1035e90e4cafSjsing size_t num;
1036e90e4cafSjsing int r;
1037e90e4cafSjsing
1038e90e4cafSjsing r1 = BIO_ctrl_pending(io2);
1039e90e4cafSjsing r2 = BIO_ctrl_get_read_request(io1);
1040e90e4cafSjsing /* here we could use ..._get_write_guarantee instead of
1041e90e4cafSjsing * ..._get_read_request, but by using the latter
1042e90e4cafSjsing * we test restartability of the SSL implementation
1043e90e4cafSjsing * more thoroughly */
1044e90e4cafSjsing num = r1;
1045e90e4cafSjsing if (r2 < num)
1046e90e4cafSjsing num = r2;
1047e90e4cafSjsing if (num) {
1048e90e4cafSjsing char *dataptr;
1049e90e4cafSjsing
1050e90e4cafSjsing if (INT_MAX < num)
1051e90e4cafSjsing num = INT_MAX;
1052e90e4cafSjsing
1053e90e4cafSjsing if (num > 1)
1054e90e4cafSjsing --num; /* test restartability even more thoroughly */
1055e90e4cafSjsing
1056e90e4cafSjsing r = BIO_nwrite0(io1, &dataptr);
1057e90e4cafSjsing assert(r > 0);
1058e90e4cafSjsing if (r < (int)num)
1059e90e4cafSjsing num = r;
1060e90e4cafSjsing r = BIO_read(io2, dataptr, (int)num);
1061e90e4cafSjsing if (r != (int)num) /* can't happen */
1062e90e4cafSjsing {
1063e90e4cafSjsing fprintf(stderr, "ERROR: BIO_read could not read "
1064e90e4cafSjsing "BIO_ctrl_pending() bytes");
1065e90e4cafSjsing goto err;
1066e90e4cafSjsing }
1067e90e4cafSjsing progress = 1;
1068e90e4cafSjsing r = BIO_nwrite(io1, &dataptr, (int)num);
1069e90e4cafSjsing if (r != (int)num) /* can't happen */
1070e90e4cafSjsing {
1071e90e4cafSjsing fprintf(stderr, "ERROR: BIO_nwrite() did not accept "
1072e90e4cafSjsing "BIO_nwrite0() bytes");
1073e90e4cafSjsing goto err;
1074e90e4cafSjsing }
1075e90e4cafSjsing
1076e90e4cafSjsing if (debug)
1077e90e4cafSjsing printf((io2 == client_io) ?
1078e90e4cafSjsing "C->S relaying: %d bytes\n" :
1079e90e4cafSjsing "S->C relaying: %d bytes\n",
1080e90e4cafSjsing (int)num);
1081e90e4cafSjsing }
1082e90e4cafSjsing } /* no loop, BIO_ctrl_get_read_request now returns 0 anyway */
1083e90e4cafSjsing
1084154f950aSjsing if (!progress && !prev_progress) {
1085e90e4cafSjsing if (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0) {
1086e90e4cafSjsing fprintf(stderr, "ERROR: got stuck\n");
1087e90e4cafSjsing goto err;
1088e90e4cafSjsing }
1089154f950aSjsing }
1090e90e4cafSjsing prev_progress = progress;
1091e90e4cafSjsing }
1092e90e4cafSjsing } while (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0);
1093e90e4cafSjsing
1094e90e4cafSjsing if (verbose)
1095e90e4cafSjsing print_details(c_ssl, "DONE via BIO pair: ");
10962011c60cSjsing
109700422117Sjsing if (verify_alpn(c_ssl, s_ssl) < 0) {
109800422117Sjsing ret = 1;
109900422117Sjsing goto err;
110000422117Sjsing }
11012011c60cSjsing
1102e90e4cafSjsing ret = 0;
1103e90e4cafSjsing
1104e90e4cafSjsing err:
1105e90e4cafSjsing ERR_print_errors(bio_err);
1106e90e4cafSjsing
1107e90e4cafSjsing BIO_free(server);
1108e90e4cafSjsing BIO_free(server_io);
1109e90e4cafSjsing BIO_free(client);
1110e90e4cafSjsing BIO_free(client_io);
1111e90e4cafSjsing BIO_free(s_ssl_bio);
1112e90e4cafSjsing BIO_free(c_ssl_bio);
1113e90e4cafSjsing
1114e90e4cafSjsing return ret;
1115e90e4cafSjsing }
11162287d13aStb #endif
1117e90e4cafSjsing
1118e90e4cafSjsing
1119e90e4cafSjsing #define W_READ 1
1120e90e4cafSjsing #define W_WRITE 2
1121e90e4cafSjsing #define C_DONE 1
1122e90e4cafSjsing #define S_DONE 2
1123e90e4cafSjsing
1124e90e4cafSjsing int
doit(SSL * s_ssl,SSL * c_ssl,long count)1125e90e4cafSjsing doit(SSL *s_ssl, SSL *c_ssl, long count)
1126e90e4cafSjsing {
1127e90e4cafSjsing char cbuf[1024*8], sbuf[1024*8];
1128e90e4cafSjsing long cw_num = count, cr_num = count;
1129e90e4cafSjsing long sw_num = count, sr_num = count;
1130e90e4cafSjsing int ret = 1;
1131e90e4cafSjsing BIO *c_to_s = NULL;
1132e90e4cafSjsing BIO *s_to_c = NULL;
1133e90e4cafSjsing BIO *c_bio = NULL;
1134e90e4cafSjsing BIO *s_bio = NULL;
1135e90e4cafSjsing int c_r, c_w, s_r, s_w;
1136e90e4cafSjsing int i, j;
1137e90e4cafSjsing int done = 0;
1138e90e4cafSjsing int c_write, s_write;
1139e90e4cafSjsing int do_server = 0, do_client = 0;
1140e90e4cafSjsing
1141e90e4cafSjsing memset(cbuf, 0, sizeof(cbuf));
1142e90e4cafSjsing memset(sbuf, 0, sizeof(sbuf));
1143e90e4cafSjsing
1144e90e4cafSjsing c_to_s = BIO_new(BIO_s_mem());
1145e90e4cafSjsing s_to_c = BIO_new(BIO_s_mem());
1146e90e4cafSjsing if ((s_to_c == NULL) || (c_to_s == NULL)) {
1147e90e4cafSjsing ERR_print_errors(bio_err);
1148e90e4cafSjsing goto err;
1149e90e4cafSjsing }
1150e90e4cafSjsing
1151e90e4cafSjsing c_bio = BIO_new(BIO_f_ssl());
1152e90e4cafSjsing s_bio = BIO_new(BIO_f_ssl());
1153e90e4cafSjsing if ((c_bio == NULL) || (s_bio == NULL)) {
1154e90e4cafSjsing ERR_print_errors(bio_err);
1155e90e4cafSjsing goto err;
1156e90e4cafSjsing }
1157e90e4cafSjsing
1158e90e4cafSjsing SSL_set_connect_state(c_ssl);
1159e90e4cafSjsing SSL_set_bio(c_ssl, s_to_c, c_to_s);
1160e90e4cafSjsing BIO_set_ssl(c_bio, c_ssl, BIO_NOCLOSE);
1161e90e4cafSjsing
1162e90e4cafSjsing SSL_set_accept_state(s_ssl);
1163e90e4cafSjsing SSL_set_bio(s_ssl, c_to_s, s_to_c);
1164e90e4cafSjsing BIO_set_ssl(s_bio, s_ssl, BIO_NOCLOSE);
1165e90e4cafSjsing
1166e90e4cafSjsing c_r = 0;
1167e90e4cafSjsing s_r = 1;
1168e90e4cafSjsing c_w = 1;
1169e90e4cafSjsing s_w = 0;
1170e90e4cafSjsing c_write = 1, s_write = 0;
1171e90e4cafSjsing
1172e90e4cafSjsing /* We can always do writes */
1173e90e4cafSjsing for (;;) {
1174e90e4cafSjsing do_server = 0;
1175e90e4cafSjsing do_client = 0;
1176e90e4cafSjsing
1177e90e4cafSjsing i = (int)BIO_pending(s_bio);
1178e90e4cafSjsing if ((i && s_r) || s_w)
1179e90e4cafSjsing do_server = 1;
1180e90e4cafSjsing
1181e90e4cafSjsing i = (int)BIO_pending(c_bio);
1182e90e4cafSjsing if ((i && c_r) || c_w)
1183e90e4cafSjsing do_client = 1;
1184e90e4cafSjsing
1185e90e4cafSjsing if (do_server && debug) {
1186e90e4cafSjsing if (SSL_in_init(s_ssl))
1187e90e4cafSjsing printf("server waiting in SSL_accept - %s\n",
1188e90e4cafSjsing SSL_state_string_long(s_ssl));
1189e90e4cafSjsing }
1190e90e4cafSjsing
1191e90e4cafSjsing if (do_client && debug) {
1192e90e4cafSjsing if (SSL_in_init(c_ssl))
1193e90e4cafSjsing printf("client waiting in SSL_connect - %s\n",
1194e90e4cafSjsing SSL_state_string_long(c_ssl));
1195e90e4cafSjsing }
1196e90e4cafSjsing
1197e90e4cafSjsing if (!do_client && !do_server) {
1198b963adf1Sjsing fprintf(stdout, "ERROR in STARTUP\n");
1199e90e4cafSjsing ERR_print_errors(bio_err);
1200b963adf1Sjsing goto err;
1201e90e4cafSjsing }
120293b15c7eSjsing
1203e90e4cafSjsing if (do_client && !(done & C_DONE)) {
1204e90e4cafSjsing if (c_write) {
1205e90e4cafSjsing j = (cw_num > (long)sizeof(cbuf)) ?
1206e90e4cafSjsing (int)sizeof(cbuf) : (int)cw_num;
1207e90e4cafSjsing i = BIO_write(c_bio, cbuf, j);
1208e90e4cafSjsing if (i < 0) {
1209e90e4cafSjsing c_r = 0;
1210e90e4cafSjsing c_w = 0;
1211e90e4cafSjsing if (BIO_should_retry(c_bio)) {
1212e90e4cafSjsing if (BIO_should_read(c_bio))
1213e90e4cafSjsing c_r = 1;
1214e90e4cafSjsing if (BIO_should_write(c_bio))
1215e90e4cafSjsing c_w = 1;
1216e90e4cafSjsing } else {
1217e90e4cafSjsing fprintf(stderr, "ERROR in CLIENT\n");
1218e90e4cafSjsing ERR_print_errors(bio_err);
1219e90e4cafSjsing goto err;
1220e90e4cafSjsing }
1221e90e4cafSjsing } else if (i == 0) {
1222e90e4cafSjsing fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
1223e90e4cafSjsing goto err;
1224e90e4cafSjsing } else {
1225e90e4cafSjsing if (debug)
1226e90e4cafSjsing printf("client wrote %d\n", i);
1227e90e4cafSjsing /* ok */
1228e90e4cafSjsing s_r = 1;
1229e90e4cafSjsing c_write = 0;
1230e90e4cafSjsing cw_num -= i;
1231e90e4cafSjsing }
1232e90e4cafSjsing } else {
1233e90e4cafSjsing i = BIO_read(c_bio, cbuf, sizeof(cbuf));
1234e90e4cafSjsing if (i < 0) {
1235e90e4cafSjsing c_r = 0;
1236e90e4cafSjsing c_w = 0;
1237e90e4cafSjsing if (BIO_should_retry(c_bio)) {
1238e90e4cafSjsing if (BIO_should_read(c_bio))
1239e90e4cafSjsing c_r = 1;
1240e90e4cafSjsing if (BIO_should_write(c_bio))
1241e90e4cafSjsing c_w = 1;
1242e90e4cafSjsing } else {
1243e90e4cafSjsing fprintf(stderr, "ERROR in CLIENT\n");
1244e90e4cafSjsing ERR_print_errors(bio_err);
1245e90e4cafSjsing goto err;
1246e90e4cafSjsing }
1247e90e4cafSjsing } else if (i == 0) {
1248e90e4cafSjsing fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
1249e90e4cafSjsing goto err;
1250e90e4cafSjsing } else {
1251e90e4cafSjsing if (debug)
1252e90e4cafSjsing printf("client read %d\n", i);
1253e90e4cafSjsing cr_num -= i;
1254e90e4cafSjsing if (sw_num > 0) {
1255e90e4cafSjsing s_write = 1;
1256e90e4cafSjsing s_w = 1;
1257e90e4cafSjsing }
1258e90e4cafSjsing if (cr_num <= 0) {
1259e90e4cafSjsing s_write = 1;
1260e90e4cafSjsing s_w = 1;
1261e90e4cafSjsing done = S_DONE|C_DONE;
1262e90e4cafSjsing }
1263e90e4cafSjsing }
1264e90e4cafSjsing }
1265e90e4cafSjsing }
1266e90e4cafSjsing
1267e90e4cafSjsing if (do_server && !(done & S_DONE)) {
1268e90e4cafSjsing if (!s_write) {
1269e90e4cafSjsing i = BIO_read(s_bio, sbuf, sizeof(cbuf));
1270e90e4cafSjsing if (i < 0) {
1271e90e4cafSjsing s_r = 0;
1272e90e4cafSjsing s_w = 0;
1273e90e4cafSjsing if (BIO_should_retry(s_bio)) {
1274e90e4cafSjsing if (BIO_should_read(s_bio))
1275e90e4cafSjsing s_r = 1;
1276e90e4cafSjsing if (BIO_should_write(s_bio))
1277e90e4cafSjsing s_w = 1;
1278e90e4cafSjsing } else {
1279e90e4cafSjsing fprintf(stderr, "ERROR in SERVER\n");
1280e90e4cafSjsing ERR_print_errors(bio_err);
1281e90e4cafSjsing goto err;
1282e90e4cafSjsing }
1283e90e4cafSjsing } else if (i == 0) {
1284e90e4cafSjsing ERR_print_errors(bio_err);
1285e90e4cafSjsing fprintf(stderr, "SSL SERVER STARTUP FAILED in SSL_read\n");
1286e90e4cafSjsing goto err;
1287e90e4cafSjsing } else {
1288e90e4cafSjsing if (debug)
1289e90e4cafSjsing printf("server read %d\n", i);
1290e90e4cafSjsing sr_num -= i;
1291e90e4cafSjsing if (cw_num > 0) {
1292e90e4cafSjsing c_write = 1;
1293e90e4cafSjsing c_w = 1;
1294e90e4cafSjsing }
1295e90e4cafSjsing if (sr_num <= 0) {
1296e90e4cafSjsing s_write = 1;
1297e90e4cafSjsing s_w = 1;
1298e90e4cafSjsing c_write = 0;
1299e90e4cafSjsing }
1300e90e4cafSjsing }
1301e90e4cafSjsing } else {
1302e90e4cafSjsing j = (sw_num > (long)sizeof(sbuf)) ?
1303e90e4cafSjsing (int)sizeof(sbuf) : (int)sw_num;
1304e90e4cafSjsing i = BIO_write(s_bio, sbuf, j);
1305e90e4cafSjsing if (i < 0) {
1306e90e4cafSjsing s_r = 0;
1307e90e4cafSjsing s_w = 0;
1308e90e4cafSjsing if (BIO_should_retry(s_bio)) {
1309e90e4cafSjsing if (BIO_should_read(s_bio))
1310e90e4cafSjsing s_r = 1;
1311e90e4cafSjsing if (BIO_should_write(s_bio))
1312e90e4cafSjsing s_w = 1;
1313e90e4cafSjsing } else {
1314e90e4cafSjsing fprintf(stderr, "ERROR in SERVER\n");
1315e90e4cafSjsing ERR_print_errors(bio_err);
1316e90e4cafSjsing goto err;
1317e90e4cafSjsing }
1318e90e4cafSjsing } else if (i == 0) {
1319e90e4cafSjsing ERR_print_errors(bio_err);
1320e90e4cafSjsing fprintf(stderr, "SSL SERVER STARTUP FAILED in SSL_write\n");
1321e90e4cafSjsing goto err;
1322e90e4cafSjsing } else {
1323e90e4cafSjsing if (debug)
1324e90e4cafSjsing printf("server wrote %d\n", i);
1325e90e4cafSjsing sw_num -= i;
1326e90e4cafSjsing s_write = 0;
1327e90e4cafSjsing c_r = 1;
1328e90e4cafSjsing if (sw_num <= 0)
1329e90e4cafSjsing done |= S_DONE;
1330e90e4cafSjsing }
1331e90e4cafSjsing }
1332e90e4cafSjsing }
1333e90e4cafSjsing
13341b38a69bSjsing if ((done & S_DONE) && (done & C_DONE))
13351b38a69bSjsing break;
1336e90e4cafSjsing }
1337e90e4cafSjsing
1338e90e4cafSjsing if (verbose)
1339e90e4cafSjsing print_details(c_ssl, "DONE: ");
13402011c60cSjsing
134100422117Sjsing if (verify_alpn(c_ssl, s_ssl) < 0) {
134200422117Sjsing ret = 1;
134300422117Sjsing goto err;
134400422117Sjsing }
13452011c60cSjsing
1346e90e4cafSjsing ret = 0;
1347e90e4cafSjsing err:
1348e90e4cafSjsing /* We have to set the BIO's to NULL otherwise they will be
1349e90e4cafSjsing * free()ed twice. Once when th s_ssl is SSL_free()ed and
1350e90e4cafSjsing * again when c_ssl is SSL_free()ed.
1351e90e4cafSjsing * This is a hack required because s_ssl and c_ssl are sharing the same
1352e90e4cafSjsing * BIO structure and SSL_set_bio() and SSL_free() automatically
1353e90e4cafSjsing * BIO_free non NULL entries.
1354e90e4cafSjsing * You should not normally do this or be required to do this */
1355e90e4cafSjsing if (s_ssl != NULL) {
1356e90e4cafSjsing s_ssl->rbio = NULL;
1357e90e4cafSjsing s_ssl->wbio = NULL;
1358e90e4cafSjsing }
1359e90e4cafSjsing if (c_ssl != NULL) {
1360e90e4cafSjsing c_ssl->rbio = NULL;
1361e90e4cafSjsing c_ssl->wbio = NULL;
1362e90e4cafSjsing }
1363e90e4cafSjsing
1364e90e4cafSjsing BIO_free(c_to_s);
1365e90e4cafSjsing BIO_free(s_to_c);
1366e90e4cafSjsing BIO_free_all(c_bio);
1367e90e4cafSjsing BIO_free_all(s_bio);
13687503bb1fSjsing
1369e90e4cafSjsing return (ret);
1370e90e4cafSjsing }
1371e90e4cafSjsing
1372e90e4cafSjsing static int
verify_callback(int ok,X509_STORE_CTX * ctx)1373e90e4cafSjsing verify_callback(int ok, X509_STORE_CTX *ctx)
1374e90e4cafSjsing {
1375f70a35c1Stb X509 *xs;
1376e90e4cafSjsing char *s, buf[256];
1377f70a35c1Stb int error, error_depth;
1378e90e4cafSjsing
1379f70a35c1Stb xs = X509_STORE_CTX_get_current_cert(ctx);
1380f70a35c1Stb s = X509_NAME_oneline(X509_get_subject_name(xs), buf, sizeof buf);
1381f70a35c1Stb error = X509_STORE_CTX_get_error(ctx);
1382f70a35c1Stb error_depth = X509_STORE_CTX_get_error_depth(ctx);
1383e90e4cafSjsing if (s != NULL) {
1384e90e4cafSjsing if (ok)
1385f70a35c1Stb fprintf(stderr, "depth=%d %s\n", error_depth, buf);
1386e90e4cafSjsing else {
1387f70a35c1Stb fprintf(stderr, "depth=%d error=%d %s\n", error_depth,
1388f70a35c1Stb error, buf);
1389e90e4cafSjsing }
1390e90e4cafSjsing }
1391e90e4cafSjsing
1392e90e4cafSjsing if (ok == 0) {
1393e90e4cafSjsing fprintf(stderr, "Error string: %s\n",
1394f70a35c1Stb X509_verify_cert_error_string(error));
1395f70a35c1Stb switch (error) {
1396e90e4cafSjsing case X509_V_ERR_CERT_NOT_YET_VALID:
1397e90e4cafSjsing case X509_V_ERR_CERT_HAS_EXPIRED:
1398e90e4cafSjsing case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
1399e90e4cafSjsing fprintf(stderr, " ... ignored.\n");
1400e90e4cafSjsing ok = 1;
1401e90e4cafSjsing }
1402e90e4cafSjsing }
1403e90e4cafSjsing
1404e90e4cafSjsing return (ok);
1405e90e4cafSjsing }
1406e90e4cafSjsing
1407e90e4cafSjsing static int
app_verify_callback(X509_STORE_CTX * ctx,void * arg)1408e90e4cafSjsing app_verify_callback(X509_STORE_CTX *ctx, void *arg)
1409e90e4cafSjsing {
1410f70a35c1Stb X509 *xs;
1411e90e4cafSjsing char *s = NULL, buf[256];
1412664ea9f8Stb const char *cb_arg = arg;
1413e90e4cafSjsing
1414f70a35c1Stb xs = X509_STORE_CTX_get0_cert(ctx);
1415e90e4cafSjsing fprintf(stderr, "In app_verify_callback, allowing cert. ");
1416664ea9f8Stb fprintf(stderr, "Arg is: %s\n", cb_arg);
1417e90e4cafSjsing fprintf(stderr, "Finished printing do we have a context? 0x%p a cert? 0x%p\n",
1418f70a35c1Stb (void *)ctx, (void *)xs);
1419f70a35c1Stb if (xs)
1420f70a35c1Stb s = X509_NAME_oneline(X509_get_subject_name(xs), buf, 256);
1421e90e4cafSjsing if (s != NULL) {
1422f70a35c1Stb fprintf(stderr, "cert depth=%d %s\n",
1423f70a35c1Stb X509_STORE_CTX_get_error_depth(ctx), buf);
1424e90e4cafSjsing }
1425e90e4cafSjsing
1426664ea9f8Stb return 1;
1427e90e4cafSjsing }
1428e90e4cafSjsing
1429e90e4cafSjsing /* These DH parameters have been generated as follows:
1430e90e4cafSjsing * $ openssl dhparam -C -noout 1024
1431e90e4cafSjsing * $ openssl dhparam -C -noout -dsaparam 1024
1432855052a0Smiod * (The second function has been renamed to avoid name conflicts.)
1433e90e4cafSjsing */
1434e90e4cafSjsing static DH *
get_dh1024(void)1435039f14fdSanton get_dh1024(void)
1436e90e4cafSjsing {
1437e90e4cafSjsing static unsigned char dh1024_p[] = {
1438e90e4cafSjsing 0xF8, 0x81, 0x89, 0x7D, 0x14, 0x24, 0xC5, 0xD1, 0xE6, 0xF7, 0xBF, 0x3A,
1439e90e4cafSjsing 0xE4, 0x90, 0xF4, 0xFC, 0x73, 0xFB, 0x34, 0xB5, 0xFA, 0x4C, 0x56, 0xA2,
1440e90e4cafSjsing 0xEA, 0xA7, 0xE9, 0xC0, 0xC0, 0xCE, 0x89, 0xE1, 0xFA, 0x63, 0x3F, 0xB0,
1441e90e4cafSjsing 0x6B, 0x32, 0x66, 0xF1, 0xD1, 0x7B, 0xB0, 0x00, 0x8F, 0xCA, 0x87, 0xC2,
1442e90e4cafSjsing 0xAE, 0x98, 0x89, 0x26, 0x17, 0xC2, 0x05, 0xD2, 0xEC, 0x08, 0xD0, 0x8C,
1443e90e4cafSjsing 0xFF, 0x17, 0x52, 0x8C, 0xC5, 0x07, 0x93, 0x03, 0xB1, 0xF6, 0x2F, 0xB8,
1444e90e4cafSjsing 0x1C, 0x52, 0x47, 0x27, 0x1B, 0xDB, 0xD1, 0x8D, 0x9D, 0x69, 0x1D, 0x52,
1445e90e4cafSjsing 0x4B, 0x32, 0x81, 0xAA, 0x7F, 0x00, 0xC8, 0xDC, 0xE6, 0xD9, 0xCC, 0xC1,
1446e90e4cafSjsing 0x11, 0x2D, 0x37, 0x34, 0x6C, 0xEA, 0x02, 0x97, 0x4B, 0x0E, 0xBB, 0xB1,
1447e90e4cafSjsing 0x71, 0x33, 0x09, 0x15, 0xFD, 0xDD, 0x23, 0x87, 0x07, 0x5E, 0x89, 0xAB,
1448e90e4cafSjsing 0x6B, 0x7C, 0x5F, 0xEC, 0xA6, 0x24, 0xDC, 0x53,
1449e90e4cafSjsing };
1450e90e4cafSjsing static unsigned char dh1024_g[] = {
1451e90e4cafSjsing 0x02,
1452e90e4cafSjsing };
1453e90e4cafSjsing DH *dh;
1454dd8e321aStb BIGNUM *dh_p = NULL, *dh_g = NULL;
1455e90e4cafSjsing
14561b38a69bSjsing if ((dh = DH_new()) == NULL)
1457dd8e321aStb return NULL;
1458dd8e321aStb
1459dd8e321aStb dh_p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
1460dd8e321aStb dh_g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
1461dd8e321aStb if (dh_p == NULL || dh_g == NULL)
1462dd8e321aStb goto err;
1463dd8e321aStb
1464dd8e321aStb if (!DH_set0_pqg(dh, dh_p, NULL, dh_g))
1465dd8e321aStb goto err;
1466dd8e321aStb
1467dd8e321aStb return dh;
1468dd8e321aStb
1469dd8e321aStb err:
1470dd8e321aStb BN_free(dh_p);
1471dd8e321aStb BN_free(dh_g);
1472e90e4cafSjsing DH_free(dh);
1473dd8e321aStb return NULL;
1474e90e4cafSjsing }
1475e90e4cafSjsing
1476e90e4cafSjsing static DH *
get_dh1024dsa(void)1477039f14fdSanton get_dh1024dsa(void)
1478e90e4cafSjsing {
1479e90e4cafSjsing static unsigned char dh1024_p[] = {
1480e90e4cafSjsing 0xC8, 0x00, 0xF7, 0x08, 0x07, 0x89, 0x4D, 0x90, 0x53, 0xF3, 0xD5, 0x00,
1481e90e4cafSjsing 0x21, 0x1B, 0xF7, 0x31, 0xA6, 0xA2, 0xDA, 0x23, 0x9A, 0xC7, 0x87, 0x19,
1482e90e4cafSjsing 0x3B, 0x47, 0xB6, 0x8C, 0x04, 0x6F, 0xFF, 0xC6, 0x9B, 0xB8, 0x65, 0xD2,
1483e90e4cafSjsing 0xC2, 0x5F, 0x31, 0x83, 0x4A, 0xA7, 0x5F, 0x2F, 0x88, 0x38, 0xB6, 0x55,
1484e90e4cafSjsing 0xCF, 0xD9, 0x87, 0x6D, 0x6F, 0x9F, 0xDA, 0xAC, 0xA6, 0x48, 0xAF, 0xFC,
1485e90e4cafSjsing 0x33, 0x84, 0x37, 0x5B, 0x82, 0x4A, 0x31, 0x5D, 0xE7, 0xBD, 0x52, 0x97,
1486e90e4cafSjsing 0xA1, 0x77, 0xBF, 0x10, 0x9E, 0x37, 0xEA, 0x64, 0xFA, 0xCA, 0x28, 0x8D,
1487e90e4cafSjsing 0x9D, 0x3B, 0xD2, 0x6E, 0x09, 0x5C, 0x68, 0xC7, 0x45, 0x90, 0xFD, 0xBB,
1488e90e4cafSjsing 0x70, 0xC9, 0x3A, 0xBB, 0xDF, 0xD4, 0x21, 0x0F, 0xC4, 0x6A, 0x3C, 0xF6,
1489e90e4cafSjsing 0x61, 0xCF, 0x3F, 0xD6, 0x13, 0xF1, 0x5F, 0xBC, 0xCF, 0xBC, 0x26, 0x9E,
1490e90e4cafSjsing 0xBC, 0x0B, 0xBD, 0xAB, 0x5D, 0xC9, 0x54, 0x39,
1491e90e4cafSjsing };
1492e90e4cafSjsing static unsigned char dh1024_g[] = {
1493e90e4cafSjsing 0x3B, 0x40, 0x86, 0xE7, 0xF3, 0x6C, 0xDE, 0x67, 0x1C, 0xCC, 0x80, 0x05,
1494e90e4cafSjsing 0x5A, 0xDF, 0xFE, 0xBD, 0x20, 0x27, 0x74, 0x6C, 0x24, 0xC9, 0x03, 0xF3,
1495e90e4cafSjsing 0xE1, 0x8D, 0xC3, 0x7D, 0x98, 0x27, 0x40, 0x08, 0xB8, 0x8C, 0x6A, 0xE9,
1496e90e4cafSjsing 0xBB, 0x1A, 0x3A, 0xD6, 0x86, 0x83, 0x5E, 0x72, 0x41, 0xCE, 0x85, 0x3C,
1497e90e4cafSjsing 0xD2, 0xB3, 0xFC, 0x13, 0xCE, 0x37, 0x81, 0x9E, 0x4C, 0x1C, 0x7B, 0x65,
1498e90e4cafSjsing 0xD3, 0xE6, 0xA6, 0x00, 0xF5, 0x5A, 0x95, 0x43, 0x5E, 0x81, 0xCF, 0x60,
1499e90e4cafSjsing 0xA2, 0x23, 0xFC, 0x36, 0xA7, 0x5D, 0x7A, 0x4C, 0x06, 0x91, 0x6E, 0xF6,
1500e90e4cafSjsing 0x57, 0xEE, 0x36, 0xCB, 0x06, 0xEA, 0xF5, 0x3D, 0x95, 0x49, 0xCB, 0xA7,
1501e90e4cafSjsing 0xDD, 0x81, 0xDF, 0x80, 0x09, 0x4A, 0x97, 0x4D, 0xA8, 0x22, 0x72, 0xA1,
1502e90e4cafSjsing 0x7F, 0xC4, 0x70, 0x56, 0x70, 0xE8, 0x20, 0x10, 0x18, 0x8F, 0x2E, 0x60,
1503e90e4cafSjsing 0x07, 0xE7, 0x68, 0x1A, 0x82, 0x5D, 0x32, 0xA2,
1504e90e4cafSjsing };
1505e90e4cafSjsing DH *dh;
1506dd8e321aStb BIGNUM *dh_p = NULL, *dh_g = NULL;
1507e90e4cafSjsing
15081b38a69bSjsing if ((dh = DH_new()) == NULL)
1509dd8e321aStb return NULL;
1510dd8e321aStb
1511dd8e321aStb dh_p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
1512dd8e321aStb dh_g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
1513dd8e321aStb if (dh_p == NULL || dh_g == NULL)
1514dd8e321aStb goto err;
1515dd8e321aStb
1516dd8e321aStb if (!DH_set0_pqg(dh, dh_p, NULL, dh_g))
1517dd8e321aStb goto err;
1518dd8e321aStb
1519dd8e321aStb DH_set_length(dh, 160);
1520dd8e321aStb
1521dd8e321aStb return dh;
1522dd8e321aStb
1523dd8e321aStb err:
1524dd8e321aStb BN_free(dh_p);
1525dd8e321aStb BN_free(dh_g);
1526e90e4cafSjsing DH_free(dh);
1527dd8e321aStb return NULL;
1528e90e4cafSjsing }
1529