ssl_test.c revision 1.1.1.2
1/* 2 * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10#include <stdio.h> 11#include <string.h> 12 13#include <openssl/conf.h> 14#include <openssl/err.h> 15#include <openssl/ssl.h> 16 17#include "handshake_helper.h" 18#include "ssl_test_ctx.h" 19#include "testutil.h" 20 21static CONF *conf = NULL; 22 23/* Currently the section names are of the form test-<number>, e.g. test-15. */ 24#define MAX_TESTCASE_NAME_LENGTH 100 25 26typedef struct ssl_test_ctx_test_fixture { 27 const char *test_case_name; 28 char test_app[MAX_TESTCASE_NAME_LENGTH]; 29} SSL_TEST_FIXTURE; 30 31static SSL_TEST_FIXTURE set_up(const char *const test_case_name) 32{ 33 SSL_TEST_FIXTURE fixture; 34 fixture.test_case_name = test_case_name; 35 return fixture; 36} 37 38static const char *print_alert(int alert) 39{ 40 return alert ? SSL_alert_desc_string_long(alert) : "no alert"; 41} 42 43static int check_result(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) 44{ 45 if (result->result != test_ctx->expected_result) { 46 fprintf(stderr, "ExpectedResult mismatch: expected %s, got %s.\n", 47 ssl_test_result_name(test_ctx->expected_result), 48 ssl_test_result_name(result->result)); 49 return 0; 50 } 51 return 1; 52} 53 54static int check_alerts(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) 55{ 56 if (result->client_alert_sent != result->client_alert_received) { 57 fprintf(stderr, "Client sent alert %s but server received %s\n.", 58 print_alert(result->client_alert_sent), 59 print_alert(result->client_alert_received)); 60 /* 61 * We can't bail here because the peer doesn't always get far enough 62 * to process a received alert. Specifically, in protocol version 63 * negotiation tests, we have the following scenario. 64 * Client supports TLS v1.2 only; Server supports TLS v1.1. 65 * Client proposes TLS v1.2; server responds with 1.1; 66 * Client now sends a protocol alert, using TLS v1.2 in the header. 67 * The server, however, rejects the alert because of version mismatch 68 * in the record layer; therefore, the server appears to never 69 * receive the alert. 70 */ 71 /* return 0; */ 72 } 73 74 if (result->server_alert_sent != result->server_alert_received) { 75 fprintf(stderr, "Server sent alert %s but client received %s\n.", 76 print_alert(result->server_alert_sent), 77 print_alert(result->server_alert_received)); 78 /* return 0; */ 79 } 80 81 /* Tolerate an alert if one wasn't explicitly specified in the test. */ 82 if (test_ctx->expected_client_alert 83 /* 84 * The info callback alert value is computed as 85 * (s->s3->send_alert[0] << 8) | s->s3->send_alert[1] 86 * where the low byte is the alert code and the high byte is other stuff. 87 */ 88 && (result->client_alert_sent & 0xff) != test_ctx->expected_client_alert) { 89 fprintf(stderr, "ClientAlert mismatch: expected %s, got %s.\n", 90 print_alert(test_ctx->expected_client_alert), 91 print_alert(result->client_alert_sent)); 92 return 0; 93 } 94 95 if (test_ctx->expected_server_alert 96 && (result->server_alert_sent & 0xff) != test_ctx->expected_server_alert) { 97 fprintf(stderr, "ServerAlert mismatch: expected %s, got %s.\n", 98 print_alert(test_ctx->expected_server_alert), 99 print_alert(result->server_alert_sent)); 100 return 0; 101 } 102 103 if (result->client_num_fatal_alerts_sent > 1) { 104 fprintf(stderr, "Client sent %d fatal alerts.\n", 105 result->client_num_fatal_alerts_sent); 106 return 0; 107 } 108 if (result->server_num_fatal_alerts_sent > 1) { 109 fprintf(stderr, "Server sent %d alerts.\n", 110 result->server_num_fatal_alerts_sent); 111 return 0; 112 } 113 return 1; 114} 115 116static int check_protocol(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) 117{ 118 if (result->client_protocol != result->server_protocol) { 119 fprintf(stderr, "Client has protocol %s but server has %s\n.", 120 ssl_protocol_name(result->client_protocol), 121 ssl_protocol_name(result->server_protocol)); 122 return 0; 123 } 124 125 if (test_ctx->expected_protocol) { 126 if (result->client_protocol != test_ctx->expected_protocol) { 127 fprintf(stderr, "Protocol mismatch: expected %s, got %s.\n", 128 ssl_protocol_name(test_ctx->expected_protocol), 129 ssl_protocol_name(result->client_protocol)); 130 return 0; 131 } 132 } 133 return 1; 134} 135 136static int check_servername(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) 137{ 138 if (result->servername != test_ctx->expected_servername) { 139 fprintf(stderr, "Client ServerName mismatch, expected %s, got %s\n.", 140 ssl_servername_name(test_ctx->expected_servername), 141 ssl_servername_name(result->servername)); 142 return 0; 143 } 144 return 1; 145} 146 147static int check_session_ticket(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) 148{ 149 if (test_ctx->session_ticket_expected == SSL_TEST_SESSION_TICKET_IGNORE) 150 return 1; 151 if (result->session_ticket != test_ctx->session_ticket_expected) { 152 fprintf(stderr, "Client SessionTicketExpected mismatch, expected %s, got %s\n.", 153 ssl_session_ticket_name(test_ctx->session_ticket_expected), 154 ssl_session_ticket_name(result->session_ticket)); 155 return 0; 156 } 157 return 1; 158} 159 160#ifndef OPENSSL_NO_NEXTPROTONEG 161static int check_npn(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) 162{ 163 int ret = 1; 164 ret &= strings_equal("NPN Negotiated (client vs server)", 165 result->client_npn_negotiated, 166 result->server_npn_negotiated); 167 ret &= strings_equal("ExpectedNPNProtocol", 168 test_ctx->expected_npn_protocol, 169 result->client_npn_negotiated); 170 return ret; 171} 172#endif 173 174static int check_alpn(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) 175{ 176 int ret = 1; 177 ret &= strings_equal("ALPN Negotiated (client vs server)", 178 result->client_alpn_negotiated, 179 result->server_alpn_negotiated); 180 ret &= strings_equal("ExpectedALPNProtocol", 181 test_ctx->expected_alpn_protocol, 182 result->client_alpn_negotiated); 183 return ret; 184} 185 186static int check_resumption(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) 187{ 188 if (result->client_resumed != result->server_resumed) { 189 fprintf(stderr, "Resumption mismatch (client vs server): %d vs %d\n", 190 result->client_resumed, result->server_resumed); 191 return 0; 192 } 193 if (result->client_resumed != test_ctx->resumption_expected) { 194 fprintf(stderr, "ResumptionExpected mismatch: %d vs %d\n", 195 test_ctx->resumption_expected, result->client_resumed); 196 return 0; 197 } 198 return 1; 199} 200 201static int check_tmp_key(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) 202{ 203 if (test_ctx->expected_tmp_key_type == 0 204 || test_ctx->expected_tmp_key_type == result->tmp_key_type) 205 return 1; 206 fprintf(stderr, "Tmp key type mismatch, %s vs %s\n", 207 OBJ_nid2ln(test_ctx->expected_tmp_key_type), 208 OBJ_nid2ln(result->tmp_key_type)); 209 return 0; 210} 211 212/* 213 * This could be further simplified by constructing an expected 214 * HANDSHAKE_RESULT, and implementing comparison methods for 215 * its fields. 216 */ 217static int check_test(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) 218{ 219 int ret = 1; 220 ret &= check_result(result, test_ctx); 221 ret &= check_alerts(result, test_ctx); 222 if (result->result == SSL_TEST_SUCCESS) { 223 ret &= check_protocol(result, test_ctx); 224 ret &= check_servername(result, test_ctx); 225 ret &= check_session_ticket(result, test_ctx); 226 ret &= (result->session_ticket_do_not_call == 0); 227#ifndef OPENSSL_NO_NEXTPROTONEG 228 ret &= check_npn(result, test_ctx); 229#endif 230 ret &= check_alpn(result, test_ctx); 231 ret &= check_resumption(result, test_ctx); 232 ret &= check_tmp_key(result, test_ctx); 233 } 234 return ret; 235} 236 237static int execute_test(SSL_TEST_FIXTURE fixture) 238{ 239 int ret = 0; 240 SSL_CTX *server_ctx = NULL, *server2_ctx = NULL, *client_ctx = NULL, 241 *resume_server_ctx = NULL, *resume_client_ctx = NULL; 242 SSL_TEST_CTX *test_ctx = NULL; 243 HANDSHAKE_RESULT *result = NULL; 244 245 test_ctx = SSL_TEST_CTX_create(conf, fixture.test_app); 246 if (test_ctx == NULL) 247 goto err; 248 249#ifndef OPENSSL_NO_DTLS 250 if (test_ctx->method == SSL_TEST_METHOD_DTLS) { 251 server_ctx = SSL_CTX_new(DTLS_server_method()); 252 TEST_check(SSL_CTX_set_max_proto_version(server_ctx, DTLS_MAX_VERSION)); 253 if (test_ctx->extra.server.servername_callback != 254 SSL_TEST_SERVERNAME_CB_NONE) { 255 server2_ctx = SSL_CTX_new(DTLS_server_method()); 256 TEST_check(server2_ctx != NULL); 257 } 258 client_ctx = SSL_CTX_new(DTLS_client_method()); 259 TEST_check(SSL_CTX_set_max_proto_version(client_ctx, DTLS_MAX_VERSION)); 260 if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RESUME) { 261 resume_server_ctx = SSL_CTX_new(DTLS_server_method()); 262 TEST_check(SSL_CTX_set_max_proto_version(resume_server_ctx, 263 DTLS_MAX_VERSION)); 264 resume_client_ctx = SSL_CTX_new(DTLS_client_method()); 265 TEST_check(SSL_CTX_set_max_proto_version(resume_client_ctx, 266 DTLS_MAX_VERSION)); 267 TEST_check(resume_server_ctx != NULL); 268 TEST_check(resume_client_ctx != NULL); 269 } 270 } 271#endif 272 if (test_ctx->method == SSL_TEST_METHOD_TLS) { 273 server_ctx = SSL_CTX_new(TLS_server_method()); 274 TEST_check(SSL_CTX_set_max_proto_version(server_ctx, TLS_MAX_VERSION)); 275 /* SNI on resumption isn't supported/tested yet. */ 276 if (test_ctx->extra.server.servername_callback != 277 SSL_TEST_SERVERNAME_CB_NONE) { 278 server2_ctx = SSL_CTX_new(TLS_server_method()); 279 TEST_check(server2_ctx != NULL); 280 } 281 client_ctx = SSL_CTX_new(TLS_client_method()); 282 TEST_check(SSL_CTX_set_max_proto_version(client_ctx, TLS_MAX_VERSION)); 283 284 if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RESUME) { 285 resume_server_ctx = SSL_CTX_new(TLS_server_method()); 286 TEST_check(SSL_CTX_set_max_proto_version(resume_server_ctx, 287 TLS_MAX_VERSION)); 288 resume_client_ctx = SSL_CTX_new(TLS_client_method()); 289 TEST_check(SSL_CTX_set_max_proto_version(resume_client_ctx, 290 TLS_MAX_VERSION)); 291 TEST_check(resume_server_ctx != NULL); 292 TEST_check(resume_client_ctx != NULL); 293 } 294 } 295 296 TEST_check(server_ctx != NULL); 297 TEST_check(client_ctx != NULL); 298 299 TEST_check(CONF_modules_load(conf, fixture.test_app, 0) > 0); 300 301 if (!SSL_CTX_config(server_ctx, "server") 302 || !SSL_CTX_config(client_ctx, "client")) { 303 goto err; 304 } 305 306 if (server2_ctx != NULL && !SSL_CTX_config(server2_ctx, "server2")) 307 goto err; 308 if (resume_server_ctx != NULL 309 && !SSL_CTX_config(resume_server_ctx, "resume-server")) 310 goto err; 311 if (resume_client_ctx != NULL 312 && !SSL_CTX_config(resume_client_ctx, "resume-client")) 313 goto err; 314 315 result = do_handshake(server_ctx, server2_ctx, client_ctx, 316 resume_server_ctx, resume_client_ctx, test_ctx); 317 318 ret = check_test(result, test_ctx); 319 320err: 321 CONF_modules_unload(0); 322 SSL_CTX_free(server_ctx); 323 SSL_CTX_free(server2_ctx); 324 SSL_CTX_free(client_ctx); 325 SSL_CTX_free(resume_server_ctx); 326 SSL_CTX_free(resume_client_ctx); 327 SSL_TEST_CTX_free(test_ctx); 328 if (ret != 1) 329 ERR_print_errors_fp(stderr); 330 HANDSHAKE_RESULT_free(result); 331 return ret; 332} 333 334static void tear_down(SSL_TEST_FIXTURE fixture) 335{ 336} 337 338#define SETUP_SSL_TEST_FIXTURE() \ 339 SETUP_TEST_FIXTURE(SSL_TEST_FIXTURE, set_up) 340#define EXECUTE_SSL_TEST() \ 341 EXECUTE_TEST(execute_test, tear_down) 342 343static int test_handshake(int idx) 344{ 345 SETUP_SSL_TEST_FIXTURE(); 346 BIO_snprintf(fixture.test_app, sizeof(fixture.test_app), 347 "test-%d", idx); 348 EXECUTE_SSL_TEST(); 349} 350 351int main(int argc, char **argv) 352{ 353 int result = 0; 354 long num_tests; 355 356 if (argc != 2) 357 return 1; 358 359 conf = NCONF_new(NULL); 360 TEST_check(conf != NULL); 361 362 /* argv[1] should point to the test conf file */ 363 TEST_check(NCONF_load(conf, argv[1], NULL) > 0); 364 365 TEST_check(NCONF_get_number_e(conf, NULL, "num_tests", &num_tests)); 366 367 ADD_ALL_TESTS(test_handshake, (int)(num_tests)); 368 result = run_tests(argv[0]); 369 370 return result; 371} 372