1025b3d3459260670a883169cf0940e94cbd79b94David Benjamin/* Copyright (c) 2014, Google Inc. 2025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * 3025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * Permission to use, copy, modify, and/or distribute this software for any 4025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * purpose with or without fee is hereby granted, provided that the above 5025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * copyright notice and this permission notice appear in all copies. 6025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * 7025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13025b3d3459260670a883169cf0940e94cbd79b94David Benjamin * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14025b3d3459260670a883169cf0940e94cbd79b94David Benjamin 15ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley#include <openssl/base.h> 16ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley 17ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley#if !defined(OPENSSL_WINDOWS) 18025b3d3459260670a883169cf0940e94cbd79b94David Benjamin#include <arpa/inet.h> 191d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin#include <netinet/in.h> 201d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin#include <signal.h> 211d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin#include <sys/socket.h> 228f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin#include <unistd.h> 23ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley#endif 24ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley 25ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley#include <sys/types.h> 26025b3d3459260670a883169cf0940e94cbd79b94David Benjamin 27025b3d3459260670a883169cf0940e94cbd79b94David Benjamin#include <openssl/bio.h> 288f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin#include <openssl/bytestring.h> 291d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin#include <openssl/ssl.h> 301d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin 3143ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin#include "async_bio.h" 326fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin#include "packeted_bio.h" 335a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin#include "test_config.h" 3443ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin 351d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjaminstatic int usage(const char *program) { 365a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin fprintf(stderr, "Usage: %s [flags...]\n", 371d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin program); 381d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin return 1; 391d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin} 40025b3d3459260670a883169cf0940e94cbd79b94David Benjamin 415a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjaminstatic int g_ex_data_index = 0; 425a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin 435a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjaminstatic void SetConfigPtr(SSL *ssl, const TestConfig *config) { 445a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin SSL_set_ex_data(ssl, g_ex_data_index, (void *)config); 455a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin} 465a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin 475a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjaminstatic const TestConfig *GetConfigPtr(SSL *ssl) { 485a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin return (const TestConfig *)SSL_get_ex_data(ssl, g_ex_data_index); 495a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin} 505a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin 51a08e49d17ad6fcf738d73647511a63bc752fe307David Benjaminstatic EVP_PKEY *LoadPrivateKey(const std::string &file) { 52a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin BIO *bio = BIO_new(BIO_s_file()); 53a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin if (bio == NULL) { 54a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin return NULL; 55a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin } 56a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin if (!BIO_read_filename(bio, file.c_str())) { 57a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin BIO_free(bio); 58a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin return NULL; 59a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin } 60a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); 61a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin BIO_free(bio); 62a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin return pkey; 63a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin} 64a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin 651f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjaminstatic int early_callback_called = 0; 668f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin 671f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjaminstatic int select_certificate_callback(const struct ssl_early_callback_ctx *ctx) { 688f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin early_callback_called = 1; 698f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin 705a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin const TestConfig *config = GetConfigPtr(ctx->ssl); 715a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin 725a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config->expected_server_name.empty()) { 737b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin return 1; 747b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin } 758f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin 767b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin const uint8_t *extension_data; 777b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin size_t extension_len; 787b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin CBS extension, server_name_list, host_name; 797b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin uint8_t name_type; 808f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin 817b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin if (!SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name, 827b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin &extension_data, 837b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin &extension_len)) { 847b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin fprintf(stderr, "Could not find server_name extension.\n"); 857b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin return -1; 867b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin } 877b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin 887b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin CBS_init(&extension, extension_data, extension_len); 897b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin if (!CBS_get_u16_length_prefixed(&extension, &server_name_list) || 907b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin CBS_len(&extension) != 0 || 917b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin !CBS_get_u8(&server_name_list, &name_type) || 927b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin name_type != TLSEXT_NAMETYPE_host_name || 937b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin !CBS_get_u16_length_prefixed(&server_name_list, &host_name) || 947b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin CBS_len(&server_name_list) != 0) { 957b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin fprintf(stderr, "Could not decode server_name extension.\n"); 967b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin return -1; 977b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin } 987b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin 995a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (!CBS_mem_equal(&host_name, 1005a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin (const uint8_t*)config->expected_server_name.data(), 1015a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin config->expected_server_name.size())) { 1027b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin fprintf(stderr, "Server name mismatch.\n"); 1038f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin } 1048f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin 1058f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin return 1; 1068f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin} 107025b3d3459260670a883169cf0940e94cbd79b94David Benjamin 1081f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjaminstatic int skip_verify(int preverify_ok, X509_STORE_CTX *store_ctx) { 10967666e7823297fa2e01291dbfe140d250dc458f2David Benjamin return 1; 11067666e7823297fa2e01291dbfe140d250dc458f2David Benjamin} 11167666e7823297fa2e01291dbfe140d250dc458f2David Benjamin 1121f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjaminstatic int next_protos_advertised_callback(SSL *ssl, 1137e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin const uint8_t **out, 1147e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin unsigned int *out_len, 1157e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin void *arg) { 1165a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin const TestConfig *config = GetConfigPtr(ssl); 1175a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config->advertise_npn.empty()) 1181f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin return SSL_TLSEXT_ERR_NOACK; 1191f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin 1201f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin // TODO(davidben): Support passing byte strings with NULs to the 1211f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin // test shim. 1225a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin *out = (const uint8_t*)config->advertise_npn.data(); 1235a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin *out_len = config->advertise_npn.size(); 1241f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin return SSL_TLSEXT_ERR_OK; 1251f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin} 1261f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin 1277e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjaminstatic int next_proto_select_callback(SSL* ssl, 1287e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin uint8_t** out, 1297e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin uint8_t* outlen, 1307e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin const uint8_t* in, 1317e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin unsigned inlen, 1327e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin void* arg) { 1335a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin const TestConfig *config = GetConfigPtr(ssl); 1345a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config->select_next_proto.empty()) 1357e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin return SSL_TLSEXT_ERR_NOACK; 1367e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin 1375a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin *out = (uint8_t*)config->select_next_proto.data(); 1385a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin *outlen = config->select_next_proto.size(); 1397e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin return SSL_TLSEXT_ERR_OK; 1407e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin} 1417e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5David Benjamin 142ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjaminstatic int alpn_select_callback(SSL* ssl, 143ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin const uint8_t** out, 144ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin uint8_t* outlen, 145ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin const uint8_t* in, 146ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin unsigned inlen, 147ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin void* arg) { 148ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin const TestConfig *config = GetConfigPtr(ssl); 149ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin if (config->select_alpn.empty()) 150ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin return SSL_TLSEXT_ERR_NOACK; 151ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin 152ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin if (!config->expected_advertised_alpn.empty() && 153ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin (config->expected_advertised_alpn.size() != inlen || 154ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin memcmp(config->expected_advertised_alpn.data(), 155ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin in, inlen) != 0)) { 156ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin fprintf(stderr, "bad ALPN select callback inputs\n"); 157ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin exit(1); 158ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin } 159ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin 160ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin *out = (const uint8_t*)config->select_alpn.data(); 161ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin *outlen = config->select_alpn.size(); 162ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin return SSL_TLSEXT_ERR_OK; 163ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin} 164ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin 165fb4ea28bb84875a844cd65a9e4a2167ec884cd48David Benjaminstatic int cookie_generate_callback(SSL *ssl, uint8_t *cookie, size_t *cookie_len) { 1666fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin *cookie_len = 32; 1676fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin memset(cookie, 42, *cookie_len); 1686fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin return 1; 1696fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin} 1706fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin 171fb4ea28bb84875a844cd65a9e4a2167ec884cd48David Benjaminstatic int cookie_verify_callback(SSL *ssl, const uint8_t *cookie, size_t cookie_len) { 1726fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin if (cookie_len != 32) { 1736fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin fprintf(stderr, "Cookie length mismatch.\n"); 1746fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin return 0; 1756fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin } 1766fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin for (size_t i = 0; i < cookie_len; i++) { 1776fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin if (cookie[i] != 42) { 1786fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin fprintf(stderr, "Cookie mismatch.\n"); 1796fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin return 0; 1806fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin } 1816fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin } 1826fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin return 1; 1836fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin} 1846fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin 1855a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjaminstatic SSL_CTX *setup_ctx(const TestConfig *config) { 186025b3d3459260670a883169cf0940e94cbd79b94David Benjamin SSL_CTX *ssl_ctx = NULL; 187f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin DH *dh = NULL; 188025b3d3459260670a883169cf0940e94cbd79b94David Benjamin 1896fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin const SSL_METHOD *method; 1906fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin if (config->is_dtls) { 1916fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin // TODO(davidben): Get DTLS 1.2 working and test the version negotiation 1926fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin // codepath. This doesn't currently work because 1936fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin // - Session resumption is broken: https://crbug.com/403378 1946fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin // - DTLS hasn't been updated for EVP_AEAD. 1956fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin if (config->is_server) { 1966fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin method = DTLSv1_server_method(); 1976fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin } else { 1986fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin method = DTLSv1_client_method(); 1996fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin } 2006fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin } else { 2016fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin if (config->is_server) { 2026fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin method = SSLv23_server_method(); 2036fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin } else { 2046fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin method = SSLv23_client_method(); 2056fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin } 2066fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin } 2076fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin ssl_ctx = SSL_CTX_new(method); 208025b3d3459260670a883169cf0940e94cbd79b94David Benjamin if (ssl_ctx == NULL) { 209025b3d3459260670a883169cf0940e94cbd79b94David Benjamin goto err; 210025b3d3459260670a883169cf0940e94cbd79b94David Benjamin } 211025b3d3459260670a883169cf0940e94cbd79b94David Benjamin 2126fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin if (config->is_dtls) { 2136fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin // DTLS needs read-ahead to function on a datagram BIO. 2146fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin // 2156fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin // TODO(davidben): this should not be necessary. DTLS code should only 2166fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin // expect a datagram BIO. 2176fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin SSL_CTX_set_read_ahead(ssl_ctx, 1); 2186fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin } 2196fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin 220025b3d3459260670a883169cf0940e94cbd79b94David Benjamin if (!SSL_CTX_set_ecdh_auto(ssl_ctx, 1)) { 221025b3d3459260670a883169cf0940e94cbd79b94David Benjamin goto err; 222025b3d3459260670a883169cf0940e94cbd79b94David Benjamin } 223025b3d3459260670a883169cf0940e94cbd79b94David Benjamin 224025b3d3459260670a883169cf0940e94cbd79b94David Benjamin if (!SSL_CTX_set_cipher_list(ssl_ctx, "ALL")) { 225025b3d3459260670a883169cf0940e94cbd79b94David Benjamin goto err; 226025b3d3459260670a883169cf0940e94cbd79b94David Benjamin } 227025b3d3459260670a883169cf0940e94cbd79b94David Benjamin 228f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin dh = DH_get_2048_256(NULL); 229f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin if (!SSL_CTX_set_tmp_dh(ssl_ctx, dh)) { 230f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin goto err; 231f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin } 232f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin 2331d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_BOTH); 2341d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin 2358f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin ssl_ctx->select_certificate_cb = select_certificate_callback; 2368f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin 2371f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin SSL_CTX_set_next_protos_advertised_cb( 2381f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin ssl_ctx, next_protos_advertised_callback, NULL); 239ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin if (!config->select_next_proto.empty()) { 240ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_callback, NULL); 241ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin } 242ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin 243ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin if (!config->select_alpn.empty()) { 244ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_callback, NULL); 245ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin } 2461f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin 2476fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin SSL_CTX_set_cookie_generate_cb(ssl_ctx, cookie_generate_callback); 2486fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin SSL_CTX_set_cookie_verify_cb(ssl_ctx, cookie_verify_callback); 2496fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin 250a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin ssl_ctx->tlsext_channel_id_enabled_new = 1; 251a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin 252f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin DH_free(dh); 2531d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin return ssl_ctx; 2541d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin 2551d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin err: 256f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin if (dh != NULL) { 257f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin DH_free(dh); 258f4e5c4e1062a0d337f0687849c410fa284d16e91David Benjamin } 2591d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin if (ssl_ctx != NULL) { 2601d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin SSL_CTX_free(ssl_ctx); 2611d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin } 2621d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin return NULL; 2631d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin} 2641d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin 26543ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjaminstatic int retry_async(SSL *ssl, int ret, BIO *bio) { 26643ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin // No error; don't retry. 26743ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin if (ret >= 0) { 26843ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin return 0; 269025b3d3459260670a883169cf0940e94cbd79b94David Benjamin } 27043ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin // See if we needed to read or write more. If so, allow one byte through on 27143ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin // the appropriate end to maximally stress the state machine. 27243ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin int err = SSL_get_error(ssl, ret); 27343ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin if (err == SSL_ERROR_WANT_READ) { 27443ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin async_bio_allow_read(bio, 1); 27543ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin return 1; 27643ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin } else if (err == SSL_ERROR_WANT_WRITE) { 27743ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin async_bio_allow_write(bio, 1); 27843ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin return 1; 279025b3d3459260670a883169cf0940e94cbd79b94David Benjamin } 28043ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin return 0; 281025b3d3459260670a883169cf0940e94cbd79b94David Benjamin} 282025b3d3459260670a883169cf0940e94cbd79b94David Benjamin 2831d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjaminstatic int do_exchange(SSL_SESSION **out_session, 2841d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin SSL_CTX *ssl_ctx, 2855a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin const TestConfig *config, 2865a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin bool is_resume, 2871d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin int fd, 2881d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin SSL_SESSION *session) { 2891d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin early_callback_called = 0; 290025b3d3459260670a883169cf0940e94cbd79b94David Benjamin 29143ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin SSL *ssl = SSL_new(ssl_ctx); 292025b3d3459260670a883169cf0940e94cbd79b94David Benjamin if (ssl == NULL) { 293025b3d3459260670a883169cf0940e94cbd79b94David Benjamin BIO_print_errors_fp(stdout); 294025b3d3459260670a883169cf0940e94cbd79b94David Benjamin return 1; 295025b3d3459260670a883169cf0940e94cbd79b94David Benjamin } 296025b3d3459260670a883169cf0940e94cbd79b94David Benjamin 2975a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin SetConfigPtr(ssl, config); 2985a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin 2995a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config->fallback_scsv) { 3005a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (!SSL_enable_fallback_scsv(ssl)) { 3015a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin BIO_print_errors_fp(stdout); 3025a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin return 1; 3035a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } 3045a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } 3055a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (!config->key_file.empty()) { 3065a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (!SSL_use_PrivateKey_file(ssl, config->key_file.c_str(), 3075a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin SSL_FILETYPE_PEM)) { 3085a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin BIO_print_errors_fp(stdout); 3095a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin return 1; 3105a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } 3115a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } 3125a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (!config->cert_file.empty()) { 3135a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (!SSL_use_certificate_file(ssl, config->cert_file.c_str(), 3145a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin SSL_FILETYPE_PEM)) { 3155a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin BIO_print_errors_fp(stdout); 316025b3d3459260670a883169cf0940e94cbd79b94David Benjamin return 1; 317025b3d3459260670a883169cf0940e94cbd79b94David Benjamin } 318025b3d3459260670a883169cf0940e94cbd79b94David Benjamin } 3195a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config->require_any_client_certificate) { 3205a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin SSL_set_verify(ssl, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 3215a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin skip_verify); 3225a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } 3235a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config->false_start) { 3245a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin SSL_set_mode(ssl, SSL_MODE_HANDSHAKE_CUTTHROUGH); 3255a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } 3265a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config->cbc_record_splitting) { 3275a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin SSL_set_mode(ssl, SSL_MODE_CBC_RECORD_SPLITTING); 3285a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } 3295a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config->partial_write) { 3305a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); 3315a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } 3325a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config->no_tls12) { 3335a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin SSL_set_options(ssl, SSL_OP_NO_TLSv1_2); 3345a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } 3355a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config->no_tls11) { 3365a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin SSL_set_options(ssl, SSL_OP_NO_TLSv1_1); 3375a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } 3385a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config->no_tls1) { 3395a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin SSL_set_options(ssl, SSL_OP_NO_TLSv1); 3405a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } 3415a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config->no_ssl3) { 3425a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin SSL_set_options(ssl, SSL_OP_NO_SSLv3); 3435a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } 3446fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin if (config->cookie_exchange) { 3456fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE); 3466fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin } 3475c24a1d6b67fd4a39ad7e34930763d85dd4b4b84David Benjamin if (config->tls_d5_bug) { 3485c24a1d6b67fd4a39ad7e34930763d85dd4b4b84David Benjamin SSL_set_options(ssl, SSL_OP_TLS_D5_BUG); 3495c24a1d6b67fd4a39ad7e34930763d85dd4b4b84David Benjamin } 350a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin if (!config->expected_channel_id.empty()) { 351a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin SSL_enable_tls_channel_id(ssl); 352a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin } 353a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin if (!config->send_channel_id.empty()) { 354a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin EVP_PKEY *pkey = LoadPrivateKey(config->send_channel_id); 355a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin if (pkey == NULL) { 356a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin BIO_print_errors_fp(stdout); 357a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin return 1; 358a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin } 359a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin SSL_enable_tls_channel_id(ssl); 360a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin if (!SSL_set1_tls_channel_id(ssl, pkey)) { 361a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin EVP_PKEY_free(pkey); 362a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin BIO_print_errors_fp(stdout); 363a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin return 1; 364a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin } 365a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin EVP_PKEY_free(pkey); 366a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin } 367e78bfded9f24725c47e0f5d0a64465566c3bdcf2David Benjamin if (!config->host_name.empty()) { 368e78bfded9f24725c47e0f5d0a64465566c3bdcf2David Benjamin SSL_set_tlsext_host_name(ssl, config->host_name.c_str()); 369e78bfded9f24725c47e0f5d0a64465566c3bdcf2David Benjamin } 370ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin if (!config->advertise_alpn.empty()) { 371ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin SSL_set_alpn_protos(ssl, (const uint8_t *)config->advertise_alpn.data(), 372ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin config->advertise_alpn.size()); 373ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin } 374025b3d3459260670a883169cf0940e94cbd79b94David Benjamin 37543ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin BIO *bio = BIO_new_fd(fd, 1 /* take ownership */); 37643ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin if (bio == NULL) { 37743ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin BIO_print_errors_fp(stdout); 37843ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin return 1; 37943ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin } 3806fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin if (config->is_dtls) { 3816fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin BIO *packeted = packeted_bio_create(); 3826fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin BIO_push(packeted, bio); 3836fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin bio = packeted; 3846fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin } 3855a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config->async) { 3866fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin BIO *async = 3876fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin config->is_dtls ? async_bio_create_datagram() : async_bio_create(); 38843ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin BIO_push(async, bio); 38943ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin bio = async; 39043ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin } 39143ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin SSL_set_bio(ssl, bio, bio); 39243ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin 3931d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin if (session != NULL) { 3941d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin if (SSL_set_session(ssl, session) != 1) { 3951d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin fprintf(stderr, "failed to set session\n"); 3961d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin return 2; 3971d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin } 3981d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin } 3991d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin 4001d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin int ret; 40143ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin do { 4025a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config->is_server) { 40343ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin ret = SSL_accept(ssl); 40443ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin } else { 40543ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin ret = SSL_connect(ssl); 40643ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin } 4075a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } while (config->async && retry_async(ssl, ret, bio)); 408025b3d3459260670a883169cf0940e94cbd79b94David Benjamin if (ret != 1) { 409025b3d3459260670a883169cf0940e94cbd79b94David Benjamin SSL_free(ssl); 410025b3d3459260670a883169cf0940e94cbd79b94David Benjamin BIO_print_errors_fp(stdout); 411025b3d3459260670a883169cf0940e94cbd79b94David Benjamin return 2; 412025b3d3459260670a883169cf0940e94cbd79b94David Benjamin } 413025b3d3459260670a883169cf0940e94cbd79b94David Benjamin 41401fe820ab957514f6b83e511492de1b3c03649d5David Benjamin if (is_resume && (SSL_session_reused(ssl) == config->expect_session_miss)) { 41501fe820ab957514f6b83e511492de1b3c03649d5David Benjamin fprintf(stderr, "session was%s reused\n", 41601fe820ab957514f6b83e511492de1b3c03649d5David Benjamin SSL_session_reused(ssl) ? "" : " not"); 4171d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin return 2; 4181d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin } 4191d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin 4205a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (!config->expected_server_name.empty()) { 421197b3abaa8e1a1954a5bf16edacf49305b1bada1David Benjamin const char *server_name = 422197b3abaa8e1a1954a5bf16edacf49305b1bada1David Benjamin SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); 4235a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (server_name != config->expected_server_name) { 424197b3abaa8e1a1954a5bf16edacf49305b1bada1David Benjamin fprintf(stderr, "servername mismatch (got %s; want %s)\n", 4255a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin server_name, config->expected_server_name.c_str()); 426197b3abaa8e1a1954a5bf16edacf49305b1bada1David Benjamin return 2; 427197b3abaa8e1a1954a5bf16edacf49305b1bada1David Benjamin } 4288f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin 4298f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin if (!early_callback_called) { 4308f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin fprintf(stderr, "early callback not called\n"); 4318f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin return 2; 4328f2c20eb7068429b5883d6e334d9cb0f0102f44dDavid Benjamin } 433197b3abaa8e1a1954a5bf16edacf49305b1bada1David Benjamin } 434197b3abaa8e1a1954a5bf16edacf49305b1bada1David Benjamin 4355a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (!config->expected_certificate_types.empty()) { 4367b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin uint8_t *certificate_types; 4377b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin int num_certificate_types = 438a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin SSL_get0_certificate_types(ssl, &certificate_types); 4395a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (num_certificate_types != 4405a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin (int)config->expected_certificate_types.size() || 4417b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin memcmp(certificate_types, 4425a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin config->expected_certificate_types.data(), 4437b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin num_certificate_types) != 0) { 4447b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin fprintf(stderr, "certificate types mismatch\n"); 4457b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin return 2; 4467b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin } 4477b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin } 4487b030511036c384ddae481345bdb52b27609bf2aDavid Benjamin 4495a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (!config->expected_next_proto.empty()) { 4501f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin const uint8_t *next_proto; 4511f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin unsigned next_proto_len; 4521f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len); 4535a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (next_proto_len != config->expected_next_proto.size() || 4545a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin memcmp(next_proto, config->expected_next_proto.data(), 4555a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin next_proto_len) != 0) { 4561f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin fprintf(stderr, "negotiated next proto mismatch\n"); 4571f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin return 2; 4581f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin } 4591f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin } 4601f5f62b20418f36954f53a4b6742f216b35b70ecDavid Benjamin 461ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin if (!config->expected_alpn.empty()) { 462ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin const uint8_t *alpn_proto; 463ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin unsigned alpn_proto_len; 464ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin SSL_get0_alpn_selected(ssl, &alpn_proto, &alpn_proto_len); 465ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin if (alpn_proto_len != config->expected_alpn.size() || 466ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin memcmp(alpn_proto, config->expected_alpn.data(), 467ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin alpn_proto_len) != 0) { 468ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin fprintf(stderr, "negotiated alpn proto mismatch\n"); 469ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin return 2; 470ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin } 471ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin } 472ae2888fbdc21ac70652034b5bfc24953a56dbe57David Benjamin 473a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin if (!config->expected_channel_id.empty()) { 474a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin uint8_t channel_id[64]; 475a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin if (!SSL_get_tls_channel_id(ssl, channel_id, sizeof(channel_id))) { 476a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin fprintf(stderr, "no channel id negotiated\n"); 477a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin return 2; 478a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin } 479a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin if (config->expected_channel_id.size() != 64 || 480a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin memcmp(config->expected_channel_id.data(), 481a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin channel_id, 64) != 0) { 482a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin fprintf(stderr, "channel id mismatch\n"); 483a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin return 2; 484a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin } 485a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin } 486a08e49d17ad6fcf738d73647511a63bc752fe307David Benjamin 4875a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config->write_different_record_sizes) { 4886fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin if (config->is_dtls) { 4896fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin fprintf(stderr, "write_different_record_sizes not supported for DTLS\n"); 4906fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin return 6; 4916fd297bb62c7097a7d3e36da2e9dbb0d7e589acbDavid Benjamin } 4927fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root // This mode writes a number of different record sizes in an attempt to 4937fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root // trip up the CBC record splitting code. 4947fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root uint8_t buf[32769]; 4957fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root memset(buf, 0x42, sizeof(buf)); 4967fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root static const size_t kRecordSizes[] = { 4977fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root 0, 1, 255, 256, 257, 16383, 16384, 16385, 32767, 32768, 32769}; 4987fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root for (size_t i = 0; i < sizeof(kRecordSizes) / sizeof(kRecordSizes[0]); 4997fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root i++) { 50043ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin int w; 5017fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root const size_t len = kRecordSizes[i]; 5027fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root size_t off = 0; 5037fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root 5047fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root if (len > sizeof(buf)) { 5057fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root fprintf(stderr, "Bad kRecordSizes value.\n"); 5067fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root return 5; 5077fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root } 5087fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root 50943ec06f705a1a3bc84ae4430b1a62a93f7f0242aDavid Benjamin do { 5107fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root w = SSL_write(ssl, buf + off, len - off); 5117fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root if (w > 0) { 5127fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root off += (size_t) w; 5137fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root } 5145a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } while ((config->async && retry_async(ssl, w, bio)) || 5155a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin (w > 0 && off < len)); 5167fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root 5177fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root if (w < 0 || off != len) { 518025b3d3459260670a883169cf0940e94cbd79b94David Benjamin SSL_free(ssl); 519025b3d3459260670a883169cf0940e94cbd79b94David Benjamin BIO_print_errors_fp(stdout); 520025b3d3459260670a883169cf0940e94cbd79b94David Benjamin return 4; 521025b3d3459260670a883169cf0940e94cbd79b94David Benjamin } 522025b3d3459260670a883169cf0940e94cbd79b94David Benjamin } 5237fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root } else { 524e58c4f53217699637e08147467a6b701b01f90d2David Benjamin if (config->shim_writes_first) { 525e58c4f53217699637e08147467a6b701b01f90d2David Benjamin int w; 526e58c4f53217699637e08147467a6b701b01f90d2David Benjamin do { 527e58c4f53217699637e08147467a6b701b01f90d2David Benjamin w = SSL_write(ssl, "hello", 5); 528e58c4f53217699637e08147467a6b701b01f90d2David Benjamin } while (config->async && retry_async(ssl, w, bio)); 529e58c4f53217699637e08147467a6b701b01f90d2David Benjamin } 5307fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root for (;;) { 5317fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root uint8_t buf[512]; 5327fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root int n; 5337fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root do { 5347fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root n = SSL_read(ssl, buf, sizeof(buf)); 5355a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } while (config->async && retry_async(ssl, n, bio)); 5367fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root if (n < 0) { 5377fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root SSL_free(ssl); 5387fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root BIO_print_errors_fp(stdout); 5397fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root return 3; 5407fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root } else if (n == 0) { 5417fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root break; 5427fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root } else { 5437fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root for (int i = 0; i < n; i++) { 5447fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root buf[i] ^= 0xff; 5457fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root } 5467fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root int w; 5477fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root do { 5487fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root w = SSL_write(ssl, buf, n); 5495a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin } while (config->async && retry_async(ssl, w, bio)); 5507fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root if (w != n) { 5517fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root SSL_free(ssl); 5527fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root BIO_print_errors_fp(stdout); 5537fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root return 4; 5547fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root } 5557fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root } 5567fdeaf11017b82368e0a97547fc491b90ad40f67Kenny Root } 557025b3d3459260670a883169cf0940e94cbd79b94David Benjamin } 558025b3d3459260670a883169cf0940e94cbd79b94David Benjamin 5591d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin if (out_session) { 5601d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin *out_session = SSL_get1_session(ssl); 5611d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin } 5621d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin 5631d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin SSL_shutdown(ssl); 564025b3d3459260670a883169cf0940e94cbd79b94David Benjamin SSL_free(ssl); 565025b3d3459260670a883169cf0940e94cbd79b94David Benjamin return 0; 566025b3d3459260670a883169cf0940e94cbd79b94David Benjamin} 5671d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin 5681d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjaminint main(int argc, char **argv) { 569ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley#if !defined(OPENSSL_WINDOWS) 5701d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin signal(SIGPIPE, SIG_IGN); 571ded93581f1674f81faa0dba4b15a842756066ab2Adam Langley#endif 5721d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin 5735a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (!SSL_library_init()) { 5745a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin return 1; 5751d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin } 5765a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin g_ex_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); 5771d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin 5785a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin TestConfig config; 5795a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (!ParseConfig(argc - 1, argv + 1, &config)) { 5801d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin return usage(argv[0]); 5811d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin } 5821d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin 5835a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin SSL_CTX *ssl_ctx = setup_ctx(&config); 5841d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin if (ssl_ctx == NULL) { 5851d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin BIO_print_errors_fp(stdout); 5861d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin return 1; 5871d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin } 5881d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin 589e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley SSL_SESSION *session = NULL; 5901d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin int ret = do_exchange(&session, 5915a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin ssl_ctx, &config, 5925a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin false /* is_resume */, 5931d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin 3 /* fd */, NULL /* session */); 5941d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin if (ret != 0) { 595e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley goto out; 5961d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin } 5971d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin 5985a593af42a2e536b37c0de7f00939961bbd510ebDavid Benjamin if (config.resume) { 599e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley ret = do_exchange(NULL, 600e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley ssl_ctx, &config, 601e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley true /* is_resume */, 602e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley 4 /* fd */, 603e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley config.is_server ? NULL : session); 6041d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin if (ret != 0) { 605e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley goto out; 6061d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin } 6071d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin } 6081d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin 609e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley ret = 0; 610e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley 611e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langleyout: 6121d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin SSL_SESSION_free(session); 6131d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin SSL_CTX_free(ssl_ctx); 614e7bf281be16331b66002b66cd2eebf7130ed5bb9Adam Langley return ret; 6151d5c83e063b4a432a6a14ea15a1a1484c8280006David Benjamin} 616