2 * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
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
12 #include <openssl/e_os2.h>
13 #include <openssl/crypto.h>
16 #include "ssl_test_ctx.h"
19 /* True enums and other test configuration values that map to an int. */
26 __owur static int parse_enum(const test_enum *enums, size_t num_enums,
27 int *value, const char *name)
30 for (i = 0; i < num_enums; i++) {
31 if (strcmp(enums[i].name, name) == 0) {
32 *value = enums[i].value;
39 static const char *enum_name(const test_enum *enums, size_t num_enums,
43 for (i = 0; i < num_enums; i++) {
44 if (enums[i].value == value) {
48 return "InvalidValue";
56 static const test_enum ssl_test_results[] = {
57 {"Success", SSL_TEST_SUCCESS},
58 {"ServerFail", SSL_TEST_SERVER_FAIL},
59 {"ClientFail", SSL_TEST_CLIENT_FAIL},
60 {"InternalError", SSL_TEST_INTERNAL_ERROR},
63 __owur static int parse_expected_result(SSL_TEST_CTX *test_ctx, const char *value)
66 if (!parse_enum(ssl_test_results, OSSL_NELEM(ssl_test_results),
70 test_ctx->expected_result = ret_value;
74 const char *ssl_test_result_name(ssl_test_result_t result)
76 return enum_name(ssl_test_results, OSSL_NELEM(ssl_test_results), result);
79 /**********************************************/
80 /* ExpectedClientAlert / ExpectedServerAlert. */
81 /**********************************************/
83 static const test_enum ssl_alerts[] = {
84 {"UnknownCA", SSL_AD_UNKNOWN_CA},
85 {"HandshakeFailure", SSL_AD_HANDSHAKE_FAILURE},
86 {"UnrecognizedName", SSL_AD_UNRECOGNIZED_NAME},
87 {"BadCertificate", SSL_AD_BAD_CERTIFICATE},
88 {"NoApplicationProtocol", SSL_AD_NO_APPLICATION_PROTOCOL},
91 __owur static int parse_alert(int *alert, const char *value)
93 return parse_enum(ssl_alerts, OSSL_NELEM(ssl_alerts), alert, value);
96 __owur static int parse_client_alert(SSL_TEST_CTX *test_ctx, const char *value)
98 return parse_alert(&test_ctx->expected_client_alert, value);
101 __owur static int parse_server_alert(SSL_TEST_CTX *test_ctx, const char *value)
103 return parse_alert(&test_ctx->expected_server_alert, value);
106 const char *ssl_alert_name(int alert)
108 return enum_name(ssl_alerts, OSSL_NELEM(ssl_alerts), alert);
111 /********************/
112 /* ExpectedProtocol */
113 /********************/
115 static const test_enum ssl_protocols[] = {
116 {"TLSv1.2", TLS1_2_VERSION},
117 {"TLSv1.1", TLS1_1_VERSION},
118 {"TLSv1", TLS1_VERSION},
119 {"SSLv3", SSL3_VERSION},
120 {"DTLSv1", DTLS1_VERSION},
121 {"DTLSv1.2", DTLS1_2_VERSION},
124 __owur static int parse_protocol(SSL_TEST_CTX *test_ctx, const char *value)
126 return parse_enum(ssl_protocols, OSSL_NELEM(ssl_protocols),
127 &test_ctx->expected_protocol, value);
130 const char *ssl_protocol_name(int protocol)
132 return enum_name(ssl_protocols, OSSL_NELEM(ssl_protocols), protocol);
135 /***********************/
136 /* VerifyCallback. */
137 /***********************/
139 static const test_enum ssl_verify_callbacks[] = {
140 {"None", SSL_TEST_VERIFY_NONE},
141 {"AcceptAll", SSL_TEST_VERIFY_ACCEPT_ALL},
142 {"RejectAll", SSL_TEST_VERIFY_REJECT_ALL},
145 __owur static int parse_client_verify_callback(SSL_TEST_CLIENT_CONF *client_conf,
149 if (!parse_enum(ssl_verify_callbacks, OSSL_NELEM(ssl_verify_callbacks),
150 &ret_value, value)) {
153 client_conf->verify_callback = ret_value;
157 const char *ssl_verify_callback_name(ssl_verify_callback_t callback)
159 return enum_name(ssl_verify_callbacks, OSSL_NELEM(ssl_verify_callbacks),
167 static const test_enum ssl_servername[] = {
168 {"None", SSL_TEST_SERVERNAME_NONE},
169 {"server1", SSL_TEST_SERVERNAME_SERVER1},
170 {"server2", SSL_TEST_SERVERNAME_SERVER2},
171 {"invalid", SSL_TEST_SERVERNAME_INVALID},
174 __owur static int parse_servername(SSL_TEST_CLIENT_CONF *client_conf,
178 if (!parse_enum(ssl_servername, OSSL_NELEM(ssl_servername),
179 &ret_value, value)) {
182 client_conf->servername = ret_value;
186 __owur static int parse_expected_servername(SSL_TEST_CTX *test_ctx,
190 if (!parse_enum(ssl_servername, OSSL_NELEM(ssl_servername),
191 &ret_value, value)) {
194 test_ctx->expected_servername = ret_value;
198 const char *ssl_servername_name(ssl_servername_t server)
200 return enum_name(ssl_servername, OSSL_NELEM(ssl_servername),
204 /**********************/
205 /* ServerNameCallback */
206 /**********************/
208 static const test_enum ssl_servername_callbacks[] = {
209 {"None", SSL_TEST_SERVERNAME_CB_NONE},
210 {"IgnoreMismatch", SSL_TEST_SERVERNAME_IGNORE_MISMATCH},
211 {"RejectMismatch", SSL_TEST_SERVERNAME_REJECT_MISMATCH},
214 __owur static int parse_servername_callback(SSL_TEST_SERVER_CONF *server_conf,
218 if (!parse_enum(ssl_servername_callbacks,
219 OSSL_NELEM(ssl_servername_callbacks), &ret_value, value)) {
222 server_conf->servername_callback = ret_value;
226 const char *ssl_servername_callback_name(ssl_servername_callback_t callback)
228 return enum_name(ssl_servername_callbacks,
229 OSSL_NELEM(ssl_servername_callbacks), callback);
232 /*************************/
233 /* SessionTicketExpected */
234 /*************************/
236 static const test_enum ssl_session_ticket[] = {
237 {"Ignore", SSL_TEST_SESSION_TICKET_IGNORE},
238 {"Yes", SSL_TEST_SESSION_TICKET_YES},
239 {"No", SSL_TEST_SESSION_TICKET_NO},
242 __owur static int parse_session_ticket(SSL_TEST_CTX *test_ctx, const char *value)
245 if (!parse_enum(ssl_session_ticket, OSSL_NELEM(ssl_session_ticket),
246 &ret_value, value)) {
249 test_ctx->session_ticket_expected = ret_value;
253 const char *ssl_session_ticket_name(ssl_session_ticket_t server)
255 return enum_name(ssl_session_ticket,
256 OSSL_NELEM(ssl_session_ticket),
260 /***********************/
262 /***********************/
264 static const test_enum ssl_test_methods[] = {
265 {"TLS", SSL_TEST_METHOD_TLS},
266 {"DTLS", SSL_TEST_METHOD_DTLS},
269 __owur static int parse_test_method(SSL_TEST_CTX *test_ctx, const char *value)
272 if (!parse_enum(ssl_test_methods, OSSL_NELEM(ssl_test_methods),
273 &ret_value, value)) {
276 test_ctx->method = ret_value;
280 const char *ssl_test_method_name(ssl_test_method_t method)
282 return enum_name(ssl_test_methods, OSSL_NELEM(ssl_test_methods), method);
285 #define IMPLEMENT_SSL_TEST_STRING_OPTION(struct_type, name, field) \
286 static int parse_##name##_##field(struct_type *ctx, const char *value) \
288 OPENSSL_free(ctx->field); \
289 ctx->field = OPENSSL_strdup(value); \
290 TEST_check(ctx->field != NULL); \
294 /************************************/
295 /* NPN and ALPN options */
296 /************************************/
298 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, npn_protocols)
299 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_SERVER_CONF, server, npn_protocols)
300 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CTX, test, expected_npn_protocol)
301 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, alpn_protocols)
302 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_SERVER_CONF, server, alpn_protocols)
303 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CTX, test, expected_alpn_protocol)
305 /***********************/
307 /***********************/
309 static const test_enum ssl_handshake_modes[] = {
310 {"Simple", SSL_TEST_HANDSHAKE_SIMPLE},
311 {"Resume", SSL_TEST_HANDSHAKE_RESUME},
312 {"Renegotiate", SSL_TEST_HANDSHAKE_RENEGOTIATE},
315 __owur static int parse_handshake_mode(SSL_TEST_CTX *test_ctx, const char *value)
318 if (!parse_enum(ssl_handshake_modes, OSSL_NELEM(ssl_handshake_modes),
319 &ret_value, value)) {
322 test_ctx->handshake_mode = ret_value;
326 const char *ssl_handshake_mode_name(ssl_handshake_mode_t mode)
328 return enum_name(ssl_handshake_modes, OSSL_NELEM(ssl_handshake_modes),
332 /***********************/
334 /***********************/
336 static const test_enum ssl_ct_validation_modes[] = {
337 {"None", SSL_TEST_CT_VALIDATION_NONE},
338 {"Permissive", SSL_TEST_CT_VALIDATION_PERMISSIVE},
339 {"Strict", SSL_TEST_CT_VALIDATION_STRICT},
342 __owur static int parse_ct_validation(SSL_TEST_CLIENT_CONF *client_conf,
346 if (!parse_enum(ssl_ct_validation_modes, OSSL_NELEM(ssl_ct_validation_modes),
347 &ret_value, value)) {
350 client_conf->ct_validation = ret_value;
354 const char *ssl_ct_validation_name(ssl_ct_validation_t mode)
356 return enum_name(ssl_ct_validation_modes, OSSL_NELEM(ssl_ct_validation_modes),
360 static int parse_boolean(const char *value, int *result)
362 if (strcasecmp(value, "Yes") == 0) {
366 else if (strcasecmp(value, "No") == 0) {
373 #define IMPLEMENT_SSL_TEST_BOOL_OPTION(struct_type, name, field) \
374 static int parse_##name##_##field(struct_type *ctx, const char *value) \
376 return parse_boolean(value, &ctx->field); \
379 IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CTX, test, resumption_expected)
380 IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_SERVER_CONF, server, broken_session_ticket)
382 /*************************************************************/
383 /* Known test options and their corresponding parse methods. */
384 /*************************************************************/
386 /* Top-level options. */
389 int (*parse)(SSL_TEST_CTX *test_ctx, const char *value);
390 } ssl_test_ctx_option;
392 static const ssl_test_ctx_option ssl_test_ctx_options[] = {
393 { "ExpectedResult", &parse_expected_result },
394 { "ExpectedClientAlert", &parse_client_alert },
395 { "ExpectedServerAlert", &parse_server_alert },
396 { "ExpectedProtocol", &parse_protocol },
397 { "ExpectedServerName", &parse_expected_servername },
398 { "SessionTicketExpected", &parse_session_ticket },
399 { "Method", &parse_test_method },
400 { "ExpectedNPNProtocol", &parse_test_expected_npn_protocol },
401 { "ExpectedALPNProtocol", &parse_test_expected_alpn_protocol },
402 { "HandshakeMode", &parse_handshake_mode },
403 { "ResumptionExpected", &parse_test_resumption_expected },
406 /* Nested client options. */
409 int (*parse)(SSL_TEST_CLIENT_CONF *conf, const char *value);
410 } ssl_test_client_option;
412 static const ssl_test_client_option ssl_test_client_options[] = {
413 { "VerifyCallback", &parse_client_verify_callback },
414 { "ServerName", &parse_servername },
415 { "NPNProtocols", &parse_client_npn_protocols },
416 { "ALPNProtocols", &parse_client_alpn_protocols },
417 { "CTValidation", &parse_ct_validation },
420 /* Nested server options. */
423 int (*parse)(SSL_TEST_SERVER_CONF *conf, const char *value);
424 } ssl_test_server_option;
426 static const ssl_test_server_option ssl_test_server_options[] = {
427 { "ServerNameCallback", &parse_servername_callback },
428 { "NPNProtocols", &parse_server_npn_protocols },
429 { "ALPNProtocols", &parse_server_alpn_protocols },
430 { "BrokenSessionTicket", &parse_server_broken_session_ticket },
434 * Since these methods are used to create tests, we use TEST_check liberally
435 * for malloc failures and other internal errors.
437 SSL_TEST_CTX *SSL_TEST_CTX_new()
440 ret = OPENSSL_zalloc(sizeof(*ret));
441 TEST_check(ret != NULL);
445 static void ssl_test_extra_conf_free_data(SSL_TEST_EXTRA_CONF *conf)
447 OPENSSL_free(conf->client.npn_protocols);
448 OPENSSL_free(conf->server.npn_protocols);
449 OPENSSL_free(conf->server2.npn_protocols);
450 OPENSSL_free(conf->client.alpn_protocols);
451 OPENSSL_free(conf->server.alpn_protocols);
452 OPENSSL_free(conf->server2.alpn_protocols);
455 static void ssl_test_ctx_free_extra_data(SSL_TEST_CTX *ctx)
457 ssl_test_extra_conf_free_data(&ctx->extra);
458 ssl_test_extra_conf_free_data(&ctx->resume_extra);
461 void SSL_TEST_CTX_free(SSL_TEST_CTX *ctx)
463 ssl_test_ctx_free_extra_data(ctx);
464 OPENSSL_free(ctx->expected_npn_protocol);
465 OPENSSL_free(ctx->expected_alpn_protocol);
469 static int parse_client_options(SSL_TEST_CLIENT_CONF *client, const CONF *conf,
470 const char *client_section)
472 STACK_OF(CONF_VALUE) *sk_conf;
476 sk_conf = NCONF_get_section(conf, client_section);
477 TEST_check(sk_conf != NULL);
479 for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) {
481 const CONF_VALUE *option = sk_CONF_VALUE_value(sk_conf, i);
482 for (j = 0; j < OSSL_NELEM(ssl_test_client_options); j++) {
483 if (strcmp(option->name, ssl_test_client_options[j].name) == 0) {
484 if (!ssl_test_client_options[j].parse(client, option->value)) {
485 fprintf(stderr, "Bad value %s for option %s\n",
486 option->value, option->name);
494 fprintf(stderr, "Unknown test option: %s\n", option->name);
502 static int parse_server_options(SSL_TEST_SERVER_CONF *server, const CONF *conf,
503 const char *server_section)
505 STACK_OF(CONF_VALUE) *sk_conf;
509 sk_conf = NCONF_get_section(conf, server_section);
510 TEST_check(sk_conf != NULL);
512 for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) {
514 const CONF_VALUE *option = sk_CONF_VALUE_value(sk_conf, i);
515 for (j = 0; j < OSSL_NELEM(ssl_test_server_options); j++) {
516 if (strcmp(option->name, ssl_test_server_options[j].name) == 0) {
517 if (!ssl_test_server_options[j].parse(server, option->value)) {
518 fprintf(stderr, "Bad value %s for option %s\n",
519 option->value, option->name);
527 fprintf(stderr, "Unknown test option: %s\n", option->name);
535 SSL_TEST_CTX *SSL_TEST_CTX_create(const CONF *conf, const char *test_section)
537 STACK_OF(CONF_VALUE) *sk_conf;
542 sk_conf = NCONF_get_section(conf, test_section);
543 TEST_check(sk_conf != NULL);
545 ctx = SSL_TEST_CTX_new();
546 TEST_check(ctx != NULL);
548 for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) {
550 const CONF_VALUE *option = sk_CONF_VALUE_value(sk_conf, i);
553 if (strcmp(option->name, "client") == 0) {
554 if (!parse_client_options(&ctx->extra.client, conf,
557 } else if (strcmp(option->name, "server") == 0) {
558 if (!parse_server_options(&ctx->extra.server, conf,
561 } else if (strcmp(option->name, "server2") == 0) {
562 if (!parse_server_options(&ctx->extra.server2, conf,
565 } else if (strcmp(option->name, "resume-client") == 0) {
566 if (!parse_client_options(&ctx->resume_extra.client, conf,
569 } else if (strcmp(option->name, "resume-server") == 0) {
570 if (!parse_server_options(&ctx->resume_extra.server, conf,
573 } else if (strcmp(option->name, "resume-server2") == 0) {
574 if (!parse_server_options(&ctx->resume_extra.server2, conf,
579 for (j = 0; j < OSSL_NELEM(ssl_test_ctx_options); j++) {
580 if (strcmp(option->name, ssl_test_ctx_options[j].name) == 0) {
581 if (!ssl_test_ctx_options[j].parse(ctx, option->value)) {
582 fprintf(stderr, "Bad value %s for option %s\n",
583 option->value, option->name);
591 fprintf(stderr, "Unknown test option: %s\n", option->name);
600 SSL_TEST_CTX_free(ctx);