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"
18 /* True enums and other test configuration values that map to an int. */
25 __owur static int parse_enum(const test_enum *enums, size_t num_enums,
26 int *value, const char *name)
29 for (i = 0; i < num_enums; i++) {
30 if (strcmp(enums[i].name, name) == 0) {
31 *value = enums[i].value;
38 static const char *enum_name(const test_enum *enums, size_t num_enums,
42 for (i = 0; i < num_enums; i++) {
43 if (enums[i].value == value) {
47 return "InvalidValue";
55 static const test_enum ssl_test_results[] = {
56 {"Success", SSL_TEST_SUCCESS},
57 {"ServerFail", SSL_TEST_SERVER_FAIL},
58 {"ClientFail", SSL_TEST_CLIENT_FAIL},
59 {"InternalError", SSL_TEST_INTERNAL_ERROR},
62 __owur static int parse_expected_result(SSL_TEST_CTX *test_ctx, const char *value)
65 if (!parse_enum(ssl_test_results, OSSL_NELEM(ssl_test_results),
69 test_ctx->expected_result = ret_value;
73 const char *ssl_test_result_name(ssl_test_result_t result)
75 return enum_name(ssl_test_results, OSSL_NELEM(ssl_test_results), result);
78 /**********************************************/
79 /* ExpectedClientAlert / ExpectedServerAlert. */
80 /**********************************************/
82 static const test_enum ssl_alerts[] = {
83 {"UnknownCA", SSL_AD_UNKNOWN_CA},
84 {"HandshakeFailure", SSL_AD_HANDSHAKE_FAILURE},
85 {"UnrecognizedName", SSL_AD_UNRECOGNIZED_NAME},
86 {"BadCertificate", SSL_AD_BAD_CERTIFICATE},
87 {"NoApplicationProtocol", SSL_AD_NO_APPLICATION_PROTOCOL},
90 __owur static int parse_alert(int *alert, const char *value)
92 return parse_enum(ssl_alerts, OSSL_NELEM(ssl_alerts), alert, value);
95 __owur static int parse_client_alert(SSL_TEST_CTX *test_ctx, const char *value)
97 return parse_alert(&test_ctx->expected_client_alert, value);
100 __owur static int parse_server_alert(SSL_TEST_CTX *test_ctx, const char *value)
102 return parse_alert(&test_ctx->expected_server_alert, value);
105 const char *ssl_alert_name(int alert)
107 return enum_name(ssl_alerts, OSSL_NELEM(ssl_alerts), alert);
110 /********************/
111 /* ExpectedProtocol */
112 /********************/
114 static const test_enum ssl_protocols[] = {
115 {"TLSv1.2", TLS1_2_VERSION},
116 {"TLSv1.1", TLS1_1_VERSION},
117 {"TLSv1", TLS1_VERSION},
118 {"SSLv3", SSL3_VERSION},
119 {"DTLSv1", DTLS1_VERSION},
120 {"DTLSv1.2", DTLS1_2_VERSION},
123 __owur static int parse_protocol(SSL_TEST_CTX *test_ctx, const char *value)
125 return parse_enum(ssl_protocols, OSSL_NELEM(ssl_protocols),
126 &test_ctx->expected_protocol, value);
129 const char *ssl_protocol_name(int protocol)
131 return enum_name(ssl_protocols, OSSL_NELEM(ssl_protocols), protocol);
134 /***********************/
135 /* VerifyCallback. */
136 /***********************/
138 static const test_enum ssl_verify_callbacks[] = {
139 {"None", SSL_TEST_VERIFY_NONE},
140 {"AcceptAll", SSL_TEST_VERIFY_ACCEPT_ALL},
141 {"RejectAll", SSL_TEST_VERIFY_REJECT_ALL},
144 __owur static int parse_client_verify_callback(SSL_TEST_CLIENT_CONF *client_conf,
148 if (!parse_enum(ssl_verify_callbacks, OSSL_NELEM(ssl_verify_callbacks),
149 &ret_value, value)) {
152 client_conf->verify_callback = ret_value;
156 const char *ssl_verify_callback_name(ssl_verify_callback_t callback)
158 return enum_name(ssl_verify_callbacks, OSSL_NELEM(ssl_verify_callbacks),
166 static const test_enum ssl_servername[] = {
167 {"None", SSL_TEST_SERVERNAME_NONE},
168 {"server1", SSL_TEST_SERVERNAME_SERVER1},
169 {"server2", SSL_TEST_SERVERNAME_SERVER2},
170 {"invalid", SSL_TEST_SERVERNAME_INVALID},
173 __owur static int parse_servername(SSL_TEST_CLIENT_CONF *client_conf,
177 if (!parse_enum(ssl_servername, OSSL_NELEM(ssl_servername),
178 &ret_value, value)) {
181 client_conf->servername = ret_value;
185 __owur static int parse_expected_servername(SSL_TEST_CTX *test_ctx,
189 if (!parse_enum(ssl_servername, OSSL_NELEM(ssl_servername),
190 &ret_value, value)) {
193 test_ctx->expected_servername = ret_value;
197 const char *ssl_servername_name(ssl_servername_t server)
199 return enum_name(ssl_servername, OSSL_NELEM(ssl_servername),
203 /**********************/
204 /* ServerNameCallback */
205 /**********************/
207 static const test_enum ssl_servername_callbacks[] = {
208 {"None", SSL_TEST_SERVERNAME_CB_NONE},
209 {"IgnoreMismatch", SSL_TEST_SERVERNAME_IGNORE_MISMATCH},
210 {"RejectMismatch", SSL_TEST_SERVERNAME_REJECT_MISMATCH},
213 __owur static int parse_servername_callback(SSL_TEST_SERVER_CONF *server_conf,
217 if (!parse_enum(ssl_servername_callbacks,
218 OSSL_NELEM(ssl_servername_callbacks), &ret_value, value)) {
221 server_conf->servername_callback = ret_value;
225 const char *ssl_servername_callback_name(ssl_servername_callback_t callback)
227 return enum_name(ssl_servername_callbacks,
228 OSSL_NELEM(ssl_servername_callbacks), callback);
231 /*************************/
232 /* SessionTicketExpected */
233 /*************************/
235 static const test_enum ssl_session_ticket[] = {
236 {"Ignore", SSL_TEST_SESSION_TICKET_IGNORE},
237 {"Yes", SSL_TEST_SESSION_TICKET_YES},
238 {"No", SSL_TEST_SESSION_TICKET_NO},
241 __owur static int parse_session_ticket(SSL_TEST_CTX *test_ctx, const char *value)
244 if (!parse_enum(ssl_session_ticket, OSSL_NELEM(ssl_session_ticket),
245 &ret_value, value)) {
248 test_ctx->session_ticket_expected = ret_value;
252 const char *ssl_session_ticket_name(ssl_session_ticket_t server)
254 return enum_name(ssl_session_ticket,
255 OSSL_NELEM(ssl_session_ticket),
259 /***********************/
261 /***********************/
263 static const test_enum ssl_test_methods[] = {
264 {"TLS", SSL_TEST_METHOD_TLS},
265 {"DTLS", SSL_TEST_METHOD_DTLS},
268 __owur static int parse_test_method(SSL_TEST_CTX *test_ctx, const char *value)
271 if (!parse_enum(ssl_test_methods, OSSL_NELEM(ssl_test_methods),
272 &ret_value, value)) {
275 test_ctx->method = ret_value;
279 const char *ssl_test_method_name(ssl_test_method_t method)
281 return enum_name(ssl_test_methods, OSSL_NELEM(ssl_test_methods), method);
284 #define IMPLEMENT_SSL_TEST_STRING_OPTION(struct_type, name, field) \
285 static int parse_##name##_##field(struct_type *ctx, const char *value) \
287 OPENSSL_free(ctx->field); \
288 ctx->field = OPENSSL_strdup(value); \
289 OPENSSL_assert(ctx->field != NULL); \
293 /************************************/
294 /* NPN and ALPN options */
295 /************************************/
297 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, npn_protocols)
298 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_SERVER_CONF, server, npn_protocols)
299 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CTX, test, expected_npn_protocol)
300 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, alpn_protocols)
301 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_SERVER_CONF, server, alpn_protocols)
302 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CTX, test, expected_alpn_protocol)
304 /***********************/
306 /***********************/
308 static const test_enum ssl_handshake_modes[] = {
309 {"Simple", SSL_TEST_HANDSHAKE_SIMPLE},
310 {"Resume", SSL_TEST_HANDSHAKE_RESUME},
311 {"Renegotiate", SSL_TEST_HANDSHAKE_RENEGOTIATE},
314 __owur static int parse_handshake_mode(SSL_TEST_CTX *test_ctx, const char *value)
317 if (!parse_enum(ssl_handshake_modes, OSSL_NELEM(ssl_handshake_modes),
318 &ret_value, value)) {
321 test_ctx->handshake_mode = ret_value;
325 const char *ssl_handshake_mode_name(ssl_handshake_mode_t mode)
327 return enum_name(ssl_handshake_modes, OSSL_NELEM(ssl_handshake_modes),
331 /***********************/
333 /***********************/
335 static const test_enum ssl_ct_validation_modes[] = {
336 {"None", SSL_TEST_CT_VALIDATION_NONE},
337 {"Permissive", SSL_TEST_CT_VALIDATION_PERMISSIVE},
338 {"Strict", SSL_TEST_CT_VALIDATION_STRICT},
341 __owur static int parse_ct_validation(SSL_TEST_CLIENT_CONF *client_conf,
345 if (!parse_enum(ssl_ct_validation_modes, OSSL_NELEM(ssl_ct_validation_modes),
346 &ret_value, value)) {
349 client_conf->ct_validation = ret_value;
353 const char *ssl_ct_validation_name(ssl_ct_validation_t mode)
355 return enum_name(ssl_ct_validation_modes, OSSL_NELEM(ssl_ct_validation_modes),
359 static int parse_boolean(const char *value, int *result)
361 if (strcasecmp(value, "Yes") == 0) {
365 else if (strcasecmp(value, "No") == 0) {
372 #define IMPLEMENT_SSL_TEST_BOOL_OPTION(struct_type, name, field) \
373 static int parse_##name##_##field(struct_type *ctx, const char *value) \
375 return parse_boolean(value, &ctx->field); \
378 IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CTX, test, resumption_expected)
379 IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_SERVER_CONF, server, broken_session_ticket)
381 /*************************************************************/
382 /* Known test options and their corresponding parse methods. */
383 /*************************************************************/
385 /* Top-level options. */
388 int (*parse)(SSL_TEST_CTX *test_ctx, const char *value);
389 } ssl_test_ctx_option;
391 static const ssl_test_ctx_option ssl_test_ctx_options[] = {
392 { "ExpectedResult", &parse_expected_result },
393 { "ExpectedClientAlert", &parse_client_alert },
394 { "ExpectedServerAlert", &parse_server_alert },
395 { "ExpectedProtocol", &parse_protocol },
396 { "ExpectedServerName", &parse_expected_servername },
397 { "SessionTicketExpected", &parse_session_ticket },
398 { "Method", &parse_test_method },
399 { "ExpectedNPNProtocol", &parse_test_expected_npn_protocol },
400 { "ExpectedALPNProtocol", &parse_test_expected_alpn_protocol },
401 { "HandshakeMode", &parse_handshake_mode },
402 { "ResumptionExpected", &parse_test_resumption_expected },
405 /* Nested client options. */
408 int (*parse)(SSL_TEST_CLIENT_CONF *conf, const char *value);
409 } ssl_test_client_option;
411 static const ssl_test_client_option ssl_test_client_options[] = {
412 { "VerifyCallback", &parse_client_verify_callback },
413 { "ServerName", &parse_servername },
414 { "NPNProtocols", &parse_client_npn_protocols },
415 { "ALPNProtocols", &parse_client_alpn_protocols },
416 { "CTValidation", &parse_ct_validation },
419 /* Nested server options. */
422 int (*parse)(SSL_TEST_SERVER_CONF *conf, const char *value);
423 } ssl_test_server_option;
425 static const ssl_test_server_option ssl_test_server_options[] = {
426 { "ServerNameCallback", &parse_servername_callback },
427 { "NPNProtocols", &parse_server_npn_protocols },
428 { "ALPNProtocols", &parse_server_alpn_protocols },
429 { "BrokenSessionTicket", &parse_server_broken_session_ticket },
433 * Since these methods are used to create tests, we use OPENSSL_assert liberally
434 * for malloc failures and other internal errors.
436 SSL_TEST_CTX *SSL_TEST_CTX_new()
439 ret = OPENSSL_zalloc(sizeof(*ret));
440 OPENSSL_assert(ret != NULL);
444 static void ssl_test_extra_conf_free_data(SSL_TEST_EXTRA_CONF *conf)
446 OPENSSL_free(conf->client.npn_protocols);
447 OPENSSL_free(conf->server.npn_protocols);
448 OPENSSL_free(conf->server2.npn_protocols);
449 OPENSSL_free(conf->client.alpn_protocols);
450 OPENSSL_free(conf->server.alpn_protocols);
451 OPENSSL_free(conf->server2.alpn_protocols);
454 static void ssl_test_ctx_free_extra_data(SSL_TEST_CTX *ctx)
456 ssl_test_extra_conf_free_data(&ctx->extra);
457 ssl_test_extra_conf_free_data(&ctx->resume_extra);
460 void SSL_TEST_CTX_free(SSL_TEST_CTX *ctx)
462 ssl_test_ctx_free_extra_data(ctx);
463 OPENSSL_free(ctx->expected_npn_protocol);
464 OPENSSL_free(ctx->expected_alpn_protocol);
468 static int parse_client_options(SSL_TEST_CLIENT_CONF *client, const CONF *conf,
469 const char *client_section)
471 STACK_OF(CONF_VALUE) *sk_conf;
475 sk_conf = NCONF_get_section(conf, client_section);
476 OPENSSL_assert(sk_conf != NULL);
478 for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) {
480 const CONF_VALUE *option = sk_CONF_VALUE_value(sk_conf, i);
481 for (j = 0; j < OSSL_NELEM(ssl_test_client_options); j++) {
482 if (strcmp(option->name, ssl_test_client_options[j].name) == 0) {
483 if (!ssl_test_client_options[j].parse(client, option->value)) {
484 fprintf(stderr, "Bad value %s for option %s\n",
485 option->value, option->name);
493 fprintf(stderr, "Unknown test option: %s\n", option->name);
501 static int parse_server_options(SSL_TEST_SERVER_CONF *server, const CONF *conf,
502 const char *server_section)
504 STACK_OF(CONF_VALUE) *sk_conf;
508 sk_conf = NCONF_get_section(conf, server_section);
509 OPENSSL_assert(sk_conf != NULL);
511 for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) {
513 const CONF_VALUE *option = sk_CONF_VALUE_value(sk_conf, i);
514 for (j = 0; j < OSSL_NELEM(ssl_test_server_options); j++) {
515 if (strcmp(option->name, ssl_test_server_options[j].name) == 0) {
516 if (!ssl_test_server_options[j].parse(server, option->value)) {
517 fprintf(stderr, "Bad value %s for option %s\n",
518 option->value, option->name);
526 fprintf(stderr, "Unknown test option: %s\n", option->name);
534 SSL_TEST_CTX *SSL_TEST_CTX_create(const CONF *conf, const char *test_section)
536 STACK_OF(CONF_VALUE) *sk_conf;
541 sk_conf = NCONF_get_section(conf, test_section);
542 OPENSSL_assert(sk_conf != NULL);
544 ctx = SSL_TEST_CTX_new();
545 OPENSSL_assert(ctx != NULL);
547 for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) {
549 const CONF_VALUE *option = sk_CONF_VALUE_value(sk_conf, i);
552 if (strcmp(option->name, "client") == 0) {
553 if (!parse_client_options(&ctx->extra.client, conf,
556 } else if (strcmp(option->name, "server") == 0) {
557 if (!parse_server_options(&ctx->extra.server, conf,
560 } else if (strcmp(option->name, "server2") == 0) {
561 if (!parse_server_options(&ctx->extra.server2, conf,
564 } else if (strcmp(option->name, "resume-client") == 0) {
565 if (!parse_client_options(&ctx->resume_extra.client, conf,
568 } else if (strcmp(option->name, "resume-server") == 0) {
569 if (!parse_server_options(&ctx->resume_extra.server, conf,
572 } else if (strcmp(option->name, "resume-server2") == 0) {
573 if (!parse_server_options(&ctx->resume_extra.server2, conf,
578 for (j = 0; j < OSSL_NELEM(ssl_test_ctx_options); j++) {
579 if (strcmp(option->name, ssl_test_ctx_options[j].name) == 0) {
580 if (!ssl_test_ctx_options[j].parse(ctx, option->value)) {
581 fprintf(stderr, "Bad value %s for option %s\n",
582 option->value, option->name);
590 fprintf(stderr, "Unknown test option: %s\n", option->name);
599 SSL_TEST_CTX_free(ctx);