1/* Copyright (c) 2014, Google Inc. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 15#include <openssl/base.h> 16 17#if !defined(OPENSSL_WINDOWS) 18#include <arpa/inet.h> 19#include <netinet/in.h> 20#include <signal.h> 21#include <sys/socket.h> 22#include <unistd.h> 23#endif 24 25#include <sys/types.h> 26 27#include <openssl/bio.h> 28#include <openssl/bytestring.h> 29#include <openssl/ssl.h> 30 31#include "async_bio.h" 32#include "packeted_bio.h" 33#include "test_config.h" 34 35static int usage(const char *program) { 36 fprintf(stderr, "Usage: %s [flags...]\n", 37 program); 38 return 1; 39} 40 41static int g_ex_data_index = 0; 42 43static void SetConfigPtr(SSL *ssl, const TestConfig *config) { 44 SSL_set_ex_data(ssl, g_ex_data_index, (void *)config); 45} 46 47static const TestConfig *GetConfigPtr(SSL *ssl) { 48 return (const TestConfig *)SSL_get_ex_data(ssl, g_ex_data_index); 49} 50 51static EVP_PKEY *LoadPrivateKey(const std::string &file) { 52 BIO *bio = BIO_new(BIO_s_file()); 53 if (bio == NULL) { 54 return NULL; 55 } 56 if (!BIO_read_filename(bio, file.c_str())) { 57 BIO_free(bio); 58 return NULL; 59 } 60 EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); 61 BIO_free(bio); 62 return pkey; 63} 64 65static int early_callback_called = 0; 66 67static int select_certificate_callback(const struct ssl_early_callback_ctx *ctx) { 68 early_callback_called = 1; 69 70 const TestConfig *config = GetConfigPtr(ctx->ssl); 71 72 if (config->expected_server_name.empty()) { 73 return 1; 74 } 75 76 const uint8_t *extension_data; 77 size_t extension_len; 78 CBS extension, server_name_list, host_name; 79 uint8_t name_type; 80 81 if (!SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name, 82 &extension_data, 83 &extension_len)) { 84 fprintf(stderr, "Could not find server_name extension.\n"); 85 return -1; 86 } 87 88 CBS_init(&extension, extension_data, extension_len); 89 if (!CBS_get_u16_length_prefixed(&extension, &server_name_list) || 90 CBS_len(&extension) != 0 || 91 !CBS_get_u8(&server_name_list, &name_type) || 92 name_type != TLSEXT_NAMETYPE_host_name || 93 !CBS_get_u16_length_prefixed(&server_name_list, &host_name) || 94 CBS_len(&server_name_list) != 0) { 95 fprintf(stderr, "Could not decode server_name extension.\n"); 96 return -1; 97 } 98 99 if (!CBS_mem_equal(&host_name, 100 (const uint8_t*)config->expected_server_name.data(), 101 config->expected_server_name.size())) { 102 fprintf(stderr, "Server name mismatch.\n"); 103 } 104 105 return 1; 106} 107 108static int skip_verify(int preverify_ok, X509_STORE_CTX *store_ctx) { 109 return 1; 110} 111 112static int next_protos_advertised_callback(SSL *ssl, 113 const uint8_t **out, 114 unsigned int *out_len, 115 void *arg) { 116 const TestConfig *config = GetConfigPtr(ssl); 117 if (config->advertise_npn.empty()) 118 return SSL_TLSEXT_ERR_NOACK; 119 120 // TODO(davidben): Support passing byte strings with NULs to the 121 // test shim. 122 *out = (const uint8_t*)config->advertise_npn.data(); 123 *out_len = config->advertise_npn.size(); 124 return SSL_TLSEXT_ERR_OK; 125} 126 127static int next_proto_select_callback(SSL* ssl, 128 uint8_t** out, 129 uint8_t* outlen, 130 const uint8_t* in, 131 unsigned inlen, 132 void* arg) { 133 const TestConfig *config = GetConfigPtr(ssl); 134 if (config->select_next_proto.empty()) 135 return SSL_TLSEXT_ERR_NOACK; 136 137 *out = (uint8_t*)config->select_next_proto.data(); 138 *outlen = config->select_next_proto.size(); 139 return SSL_TLSEXT_ERR_OK; 140} 141 142static int alpn_select_callback(SSL* ssl, 143 const uint8_t** out, 144 uint8_t* outlen, 145 const uint8_t* in, 146 unsigned inlen, 147 void* arg) { 148 const TestConfig *config = GetConfigPtr(ssl); 149 if (config->select_alpn.empty()) 150 return SSL_TLSEXT_ERR_NOACK; 151 152 if (!config->expected_advertised_alpn.empty() && 153 (config->expected_advertised_alpn.size() != inlen || 154 memcmp(config->expected_advertised_alpn.data(), 155 in, inlen) != 0)) { 156 fprintf(stderr, "bad ALPN select callback inputs\n"); 157 exit(1); 158 } 159 160 *out = (const uint8_t*)config->select_alpn.data(); 161 *outlen = config->select_alpn.size(); 162 return SSL_TLSEXT_ERR_OK; 163} 164 165static int cookie_generate_callback(SSL *ssl, uint8_t *cookie, size_t *cookie_len) { 166 *cookie_len = 32; 167 memset(cookie, 42, *cookie_len); 168 return 1; 169} 170 171static int cookie_verify_callback(SSL *ssl, const uint8_t *cookie, size_t cookie_len) { 172 if (cookie_len != 32) { 173 fprintf(stderr, "Cookie length mismatch.\n"); 174 return 0; 175 } 176 for (size_t i = 0; i < cookie_len; i++) { 177 if (cookie[i] != 42) { 178 fprintf(stderr, "Cookie mismatch.\n"); 179 return 0; 180 } 181 } 182 return 1; 183} 184 185static SSL_CTX *setup_ctx(const TestConfig *config) { 186 SSL_CTX *ssl_ctx = NULL; 187 DH *dh = NULL; 188 189 const SSL_METHOD *method; 190 if (config->is_dtls) { 191 // TODO(davidben): Get DTLS 1.2 working and test the version negotiation 192 // codepath. This doesn't currently work because 193 // - Session resumption is broken: https://crbug.com/403378 194 // - DTLS hasn't been updated for EVP_AEAD. 195 if (config->is_server) { 196 method = DTLSv1_server_method(); 197 } else { 198 method = DTLSv1_client_method(); 199 } 200 } else { 201 if (config->is_server) { 202 method = SSLv23_server_method(); 203 } else { 204 method = SSLv23_client_method(); 205 } 206 } 207 ssl_ctx = SSL_CTX_new(method); 208 if (ssl_ctx == NULL) { 209 goto err; 210 } 211 212 if (config->is_dtls) { 213 // DTLS needs read-ahead to function on a datagram BIO. 214 // 215 // TODO(davidben): this should not be necessary. DTLS code should only 216 // expect a datagram BIO. 217 SSL_CTX_set_read_ahead(ssl_ctx, 1); 218 } 219 220 if (!SSL_CTX_set_ecdh_auto(ssl_ctx, 1)) { 221 goto err; 222 } 223 224 if (!SSL_CTX_set_cipher_list(ssl_ctx, "ALL")) { 225 goto err; 226 } 227 228 dh = DH_get_2048_256(NULL); 229 if (!SSL_CTX_set_tmp_dh(ssl_ctx, dh)) { 230 goto err; 231 } 232 233 SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_BOTH); 234 235 ssl_ctx->select_certificate_cb = select_certificate_callback; 236 237 SSL_CTX_set_next_protos_advertised_cb( 238 ssl_ctx, next_protos_advertised_callback, NULL); 239 if (!config->select_next_proto.empty()) { 240 SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_callback, NULL); 241 } 242 243 if (!config->select_alpn.empty()) { 244 SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_callback, NULL); 245 } 246 247 SSL_CTX_set_cookie_generate_cb(ssl_ctx, cookie_generate_callback); 248 SSL_CTX_set_cookie_verify_cb(ssl_ctx, cookie_verify_callback); 249 250 ssl_ctx->tlsext_channel_id_enabled_new = 1; 251 252 DH_free(dh); 253 return ssl_ctx; 254 255 err: 256 if (dh != NULL) { 257 DH_free(dh); 258 } 259 if (ssl_ctx != NULL) { 260 SSL_CTX_free(ssl_ctx); 261 } 262 return NULL; 263} 264 265static int retry_async(SSL *ssl, int ret, BIO *bio) { 266 // No error; don't retry. 267 if (ret >= 0) { 268 return 0; 269 } 270 // See if we needed to read or write more. If so, allow one byte through on 271 // the appropriate end to maximally stress the state machine. 272 int err = SSL_get_error(ssl, ret); 273 if (err == SSL_ERROR_WANT_READ) { 274 async_bio_allow_read(bio, 1); 275 return 1; 276 } else if (err == SSL_ERROR_WANT_WRITE) { 277 async_bio_allow_write(bio, 1); 278 return 1; 279 } 280 return 0; 281} 282 283static int do_exchange(SSL_SESSION **out_session, 284 SSL_CTX *ssl_ctx, 285 const TestConfig *config, 286 bool is_resume, 287 int fd, 288 SSL_SESSION *session) { 289 early_callback_called = 0; 290 291 SSL *ssl = SSL_new(ssl_ctx); 292 if (ssl == NULL) { 293 BIO_print_errors_fp(stdout); 294 return 1; 295 } 296 297 SetConfigPtr(ssl, config); 298 299 if (config->fallback_scsv) { 300 if (!SSL_enable_fallback_scsv(ssl)) { 301 BIO_print_errors_fp(stdout); 302 return 1; 303 } 304 } 305 if (!config->key_file.empty()) { 306 if (!SSL_use_PrivateKey_file(ssl, config->key_file.c_str(), 307 SSL_FILETYPE_PEM)) { 308 BIO_print_errors_fp(stdout); 309 return 1; 310 } 311 } 312 if (!config->cert_file.empty()) { 313 if (!SSL_use_certificate_file(ssl, config->cert_file.c_str(), 314 SSL_FILETYPE_PEM)) { 315 BIO_print_errors_fp(stdout); 316 return 1; 317 } 318 } 319 if (config->require_any_client_certificate) { 320 SSL_set_verify(ssl, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 321 skip_verify); 322 } 323 if (config->false_start) { 324 SSL_set_mode(ssl, SSL_MODE_HANDSHAKE_CUTTHROUGH); 325 } 326 if (config->cbc_record_splitting) { 327 SSL_set_mode(ssl, SSL_MODE_CBC_RECORD_SPLITTING); 328 } 329 if (config->partial_write) { 330 SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); 331 } 332 if (config->no_tls12) { 333 SSL_set_options(ssl, SSL_OP_NO_TLSv1_2); 334 } 335 if (config->no_tls11) { 336 SSL_set_options(ssl, SSL_OP_NO_TLSv1_1); 337 } 338 if (config->no_tls1) { 339 SSL_set_options(ssl, SSL_OP_NO_TLSv1); 340 } 341 if (config->no_ssl3) { 342 SSL_set_options(ssl, SSL_OP_NO_SSLv3); 343 } 344 if (config->cookie_exchange) { 345 SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE); 346 } 347 if (config->tls_d5_bug) { 348 SSL_set_options(ssl, SSL_OP_TLS_D5_BUG); 349 } 350 if (!config->expected_channel_id.empty()) { 351 SSL_enable_tls_channel_id(ssl); 352 } 353 if (!config->send_channel_id.empty()) { 354 EVP_PKEY *pkey = LoadPrivateKey(config->send_channel_id); 355 if (pkey == NULL) { 356 BIO_print_errors_fp(stdout); 357 return 1; 358 } 359 SSL_enable_tls_channel_id(ssl); 360 if (!SSL_set1_tls_channel_id(ssl, pkey)) { 361 EVP_PKEY_free(pkey); 362 BIO_print_errors_fp(stdout); 363 return 1; 364 } 365 EVP_PKEY_free(pkey); 366 } 367 if (!config->host_name.empty()) { 368 SSL_set_tlsext_host_name(ssl, config->host_name.c_str()); 369 } 370 if (!config->advertise_alpn.empty()) { 371 SSL_set_alpn_protos(ssl, (const uint8_t *)config->advertise_alpn.data(), 372 config->advertise_alpn.size()); 373 } 374 375 BIO *bio = BIO_new_fd(fd, 1 /* take ownership */); 376 if (bio == NULL) { 377 BIO_print_errors_fp(stdout); 378 return 1; 379 } 380 if (config->is_dtls) { 381 BIO *packeted = packeted_bio_create(); 382 BIO_push(packeted, bio); 383 bio = packeted; 384 } 385 if (config->async) { 386 BIO *async = 387 config->is_dtls ? async_bio_create_datagram() : async_bio_create(); 388 BIO_push(async, bio); 389 bio = async; 390 } 391 SSL_set_bio(ssl, bio, bio); 392 393 if (session != NULL) { 394 if (SSL_set_session(ssl, session) != 1) { 395 fprintf(stderr, "failed to set session\n"); 396 return 2; 397 } 398 } 399 400 int ret; 401 do { 402 if (config->is_server) { 403 ret = SSL_accept(ssl); 404 } else { 405 ret = SSL_connect(ssl); 406 } 407 } while (config->async && retry_async(ssl, ret, bio)); 408 if (ret != 1) { 409 SSL_free(ssl); 410 BIO_print_errors_fp(stdout); 411 return 2; 412 } 413 414 if (is_resume && (SSL_session_reused(ssl) == config->expect_session_miss)) { 415 fprintf(stderr, "session was%s reused\n", 416 SSL_session_reused(ssl) ? "" : " not"); 417 return 2; 418 } 419 420 if (!config->expected_server_name.empty()) { 421 const char *server_name = 422 SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); 423 if (server_name != config->expected_server_name) { 424 fprintf(stderr, "servername mismatch (got %s; want %s)\n", 425 server_name, config->expected_server_name.c_str()); 426 return 2; 427 } 428 429 if (!early_callback_called) { 430 fprintf(stderr, "early callback not called\n"); 431 return 2; 432 } 433 } 434 435 if (!config->expected_certificate_types.empty()) { 436 uint8_t *certificate_types; 437 int num_certificate_types = 438 SSL_get0_certificate_types(ssl, &certificate_types); 439 if (num_certificate_types != 440 (int)config->expected_certificate_types.size() || 441 memcmp(certificate_types, 442 config->expected_certificate_types.data(), 443 num_certificate_types) != 0) { 444 fprintf(stderr, "certificate types mismatch\n"); 445 return 2; 446 } 447 } 448 449 if (!config->expected_next_proto.empty()) { 450 const uint8_t *next_proto; 451 unsigned next_proto_len; 452 SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len); 453 if (next_proto_len != config->expected_next_proto.size() || 454 memcmp(next_proto, config->expected_next_proto.data(), 455 next_proto_len) != 0) { 456 fprintf(stderr, "negotiated next proto mismatch\n"); 457 return 2; 458 } 459 } 460 461 if (!config->expected_alpn.empty()) { 462 const uint8_t *alpn_proto; 463 unsigned alpn_proto_len; 464 SSL_get0_alpn_selected(ssl, &alpn_proto, &alpn_proto_len); 465 if (alpn_proto_len != config->expected_alpn.size() || 466 memcmp(alpn_proto, config->expected_alpn.data(), 467 alpn_proto_len) != 0) { 468 fprintf(stderr, "negotiated alpn proto mismatch\n"); 469 return 2; 470 } 471 } 472 473 if (!config->expected_channel_id.empty()) { 474 uint8_t channel_id[64]; 475 if (!SSL_get_tls_channel_id(ssl, channel_id, sizeof(channel_id))) { 476 fprintf(stderr, "no channel id negotiated\n"); 477 return 2; 478 } 479 if (config->expected_channel_id.size() != 64 || 480 memcmp(config->expected_channel_id.data(), 481 channel_id, 64) != 0) { 482 fprintf(stderr, "channel id mismatch\n"); 483 return 2; 484 } 485 } 486 487 if (config->write_different_record_sizes) { 488 if (config->is_dtls) { 489 fprintf(stderr, "write_different_record_sizes not supported for DTLS\n"); 490 return 6; 491 } 492 // This mode writes a number of different record sizes in an attempt to 493 // trip up the CBC record splitting code. 494 uint8_t buf[32769]; 495 memset(buf, 0x42, sizeof(buf)); 496 static const size_t kRecordSizes[] = { 497 0, 1, 255, 256, 257, 16383, 16384, 16385, 32767, 32768, 32769}; 498 for (size_t i = 0; i < sizeof(kRecordSizes) / sizeof(kRecordSizes[0]); 499 i++) { 500 int w; 501 const size_t len = kRecordSizes[i]; 502 size_t off = 0; 503 504 if (len > sizeof(buf)) { 505 fprintf(stderr, "Bad kRecordSizes value.\n"); 506 return 5; 507 } 508 509 do { 510 w = SSL_write(ssl, buf + off, len - off); 511 if (w > 0) { 512 off += (size_t) w; 513 } 514 } while ((config->async && retry_async(ssl, w, bio)) || 515 (w > 0 && off < len)); 516 517 if (w < 0 || off != len) { 518 SSL_free(ssl); 519 BIO_print_errors_fp(stdout); 520 return 4; 521 } 522 } 523 } else { 524 if (config->shim_writes_first) { 525 int w; 526 do { 527 w = SSL_write(ssl, "hello", 5); 528 } while (config->async && retry_async(ssl, w, bio)); 529 } 530 for (;;) { 531 uint8_t buf[512]; 532 int n; 533 do { 534 n = SSL_read(ssl, buf, sizeof(buf)); 535 } while (config->async && retry_async(ssl, n, bio)); 536 if (n < 0) { 537 SSL_free(ssl); 538 BIO_print_errors_fp(stdout); 539 return 3; 540 } else if (n == 0) { 541 break; 542 } else { 543 for (int i = 0; i < n; i++) { 544 buf[i] ^= 0xff; 545 } 546 int w; 547 do { 548 w = SSL_write(ssl, buf, n); 549 } while (config->async && retry_async(ssl, w, bio)); 550 if (w != n) { 551 SSL_free(ssl); 552 BIO_print_errors_fp(stdout); 553 return 4; 554 } 555 } 556 } 557 } 558 559 if (out_session) { 560 *out_session = SSL_get1_session(ssl); 561 } 562 563 SSL_shutdown(ssl); 564 SSL_free(ssl); 565 return 0; 566} 567 568int main(int argc, char **argv) { 569#if !defined(OPENSSL_WINDOWS) 570 signal(SIGPIPE, SIG_IGN); 571#endif 572 573 if (!SSL_library_init()) { 574 return 1; 575 } 576 g_ex_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); 577 578 TestConfig config; 579 if (!ParseConfig(argc - 1, argv + 1, &config)) { 580 return usage(argv[0]); 581 } 582 583 SSL_CTX *ssl_ctx = setup_ctx(&config); 584 if (ssl_ctx == NULL) { 585 BIO_print_errors_fp(stdout); 586 return 1; 587 } 588 589 SSL_SESSION *session = NULL; 590 int ret = do_exchange(&session, 591 ssl_ctx, &config, 592 false /* is_resume */, 593 3 /* fd */, NULL /* session */); 594 if (ret != 0) { 595 goto out; 596 } 597 598 if (config.resume) { 599 ret = do_exchange(NULL, 600 ssl_ctx, &config, 601 true /* is_resume */, 602 4 /* fd */, 603 config.is_server ? NULL : session); 604 if (ret != 0) { 605 goto out; 606 } 607 } 608 609 ret = 0; 610 611out: 612 SSL_SESSION_free(session); 613 SSL_CTX_free(ssl_ctx); 614 return ret; 615} 616