]>
Commit | Line | Data |
---|---|---|
453dfd8d | 1 | /* |
8fe3127c | 2 | * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. |
453dfd8d | 3 | * |
440e5d80 RS |
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 | |
453dfd8d | 7 | * https://www.openssl.org/source/license.html |
453dfd8d EK |
8 | */ |
9 | ||
07016a8a | 10 | #include "../e_os.h" |
453dfd8d EK |
11 | #include <string.h> |
12 | ||
13 | #include <openssl/e_os2.h> | |
14 | #include <openssl/crypto.h> | |
15 | ||
176db6dc | 16 | #include "internal/nelem.h" |
453dfd8d | 17 | #include "ssl_test_ctx.h" |
d61f0078 | 18 | #include "testutil.h" |
453dfd8d | 19 | |
e0421bd8 | 20 | static const int default_app_data_size = 256; |
6dc99745 EK |
21 | /* Default set to be as small as possible to exercise fragmentation. */ |
22 | static const int default_max_fragment_size = 512; | |
e0421bd8 EK |
23 | |
24 | static int parse_boolean(const char *value, int *result) | |
25 | { | |
26 | if (strcasecmp(value, "Yes") == 0) { | |
27 | *result = 1; | |
28 | return 1; | |
29 | } | |
30 | else if (strcasecmp(value, "No") == 0) { | |
31 | *result = 0; | |
32 | return 1; | |
33 | } | |
019e47ce | 34 | TEST_error("parse_boolean given: '%s'", value); |
e0421bd8 EK |
35 | return 0; |
36 | } | |
37 | ||
38 | #define IMPLEMENT_SSL_TEST_BOOL_OPTION(struct_type, name, field) \ | |
39 | static int parse_##name##_##field(struct_type *ctx, const char *value) \ | |
40 | { \ | |
41 | return parse_boolean(value, &ctx->field); \ | |
42 | } | |
43 | ||
44 | #define IMPLEMENT_SSL_TEST_STRING_OPTION(struct_type, name, field) \ | |
45 | static int parse_##name##_##field(struct_type *ctx, const char *value) \ | |
46 | { \ | |
47 | OPENSSL_free(ctx->field); \ | |
48 | ctx->field = OPENSSL_strdup(value); \ | |
019e47ce | 49 | return TEST_ptr(ctx->field); \ |
e0421bd8 EK |
50 | } |
51 | ||
52 | #define IMPLEMENT_SSL_TEST_INT_OPTION(struct_type, name, field) \ | |
53 | static int parse_##name##_##field(struct_type *ctx, const char *value) \ | |
54 | { \ | |
55 | ctx->field = atoi(value); \ | |
56 | return 1; \ | |
57 | } | |
58 | ||
453dfd8d EK |
59 | /* True enums and other test configuration values that map to an int. */ |
60 | typedef struct { | |
61 | const char *name; | |
62 | int value; | |
63 | } test_enum; | |
64 | ||
65 | ||
66 | __owur static int parse_enum(const test_enum *enums, size_t num_enums, | |
67 | int *value, const char *name) | |
68 | { | |
69 | size_t i; | |
70 | for (i = 0; i < num_enums; i++) { | |
71 | if (strcmp(enums[i].name, name) == 0) { | |
72 | *value = enums[i].value; | |
73 | return 1; | |
74 | } | |
75 | } | |
76 | return 0; | |
77 | } | |
78 | ||
79 | static const char *enum_name(const test_enum *enums, size_t num_enums, | |
80 | int value) | |
81 | { | |
82 | size_t i; | |
83 | for (i = 0; i < num_enums; i++) { | |
84 | if (enums[i].value == value) { | |
85 | return enums[i].name; | |
86 | } | |
87 | } | |
88 | return "InvalidValue"; | |
89 | } | |
90 | ||
91 | ||
cc22cd54 | 92 | /* ExpectedResult */ |
453dfd8d EK |
93 | |
94 | static const test_enum ssl_test_results[] = { | |
95 | {"Success", SSL_TEST_SUCCESS}, | |
96 | {"ServerFail", SSL_TEST_SERVER_FAIL}, | |
97 | {"ClientFail", SSL_TEST_CLIENT_FAIL}, | |
98 | {"InternalError", SSL_TEST_INTERNAL_ERROR}, | |
99 | }; | |
100 | ||
101 | __owur static int parse_expected_result(SSL_TEST_CTX *test_ctx, const char *value) | |
102 | { | |
103 | int ret_value; | |
104 | if (!parse_enum(ssl_test_results, OSSL_NELEM(ssl_test_results), | |
105 | &ret_value, value)) { | |
106 | return 0; | |
107 | } | |
108 | test_ctx->expected_result = ret_value; | |
109 | return 1; | |
110 | } | |
111 | ||
a263f320 | 112 | const char *ssl_test_result_name(ssl_test_result_t result) |
453dfd8d EK |
113 | { |
114 | return enum_name(ssl_test_results, OSSL_NELEM(ssl_test_results), result); | |
115 | } | |
116 | ||
cc22cd54 | 117 | /* ExpectedClientAlert / ExpectedServerAlert */ |
453dfd8d EK |
118 | |
119 | static const test_enum ssl_alerts[] = { | |
120 | {"UnknownCA", SSL_AD_UNKNOWN_CA}, | |
a263f320 | 121 | {"HandshakeFailure", SSL_AD_HANDSHAKE_FAILURE}, |
d2b23cd2 | 122 | {"UnrecognizedName", SSL_AD_UNRECOGNIZED_NAME}, |
ce2cdac2 EK |
123 | {"BadCertificate", SSL_AD_BAD_CERTIFICATE}, |
124 | {"NoApplicationProtocol", SSL_AD_NO_APPLICATION_PROTOCOL}, | |
453dfd8d EK |
125 | }; |
126 | ||
127 | __owur static int parse_alert(int *alert, const char *value) | |
128 | { | |
129 | return parse_enum(ssl_alerts, OSSL_NELEM(ssl_alerts), alert, value); | |
130 | } | |
131 | ||
132 | __owur static int parse_client_alert(SSL_TEST_CTX *test_ctx, const char *value) | |
133 | { | |
9f48bbac | 134 | return parse_alert(&test_ctx->expected_client_alert, value); |
453dfd8d EK |
135 | } |
136 | ||
137 | __owur static int parse_server_alert(SSL_TEST_CTX *test_ctx, const char *value) | |
138 | { | |
9f48bbac | 139 | return parse_alert(&test_ctx->expected_server_alert, value); |
453dfd8d EK |
140 | } |
141 | ||
142 | const char *ssl_alert_name(int alert) | |
143 | { | |
144 | return enum_name(ssl_alerts, OSSL_NELEM(ssl_alerts), alert); | |
145 | } | |
146 | ||
9f48bbac | 147 | /* ExpectedProtocol */ |
453dfd8d EK |
148 | |
149 | static const test_enum ssl_protocols[] = { | |
582a17d6 | 150 | {"TLSv1.3", TLS1_3_VERSION}, |
453dfd8d EK |
151 | {"TLSv1.2", TLS1_2_VERSION}, |
152 | {"TLSv1.1", TLS1_1_VERSION}, | |
153 | {"TLSv1", TLS1_VERSION}, | |
154 | {"SSLv3", SSL3_VERSION}, | |
74726750 EK |
155 | {"DTLSv1", DTLS1_VERSION}, |
156 | {"DTLSv1.2", DTLS1_2_VERSION}, | |
453dfd8d EK |
157 | }; |
158 | ||
159 | __owur static int parse_protocol(SSL_TEST_CTX *test_ctx, const char *value) | |
160 | { | |
161 | return parse_enum(ssl_protocols, OSSL_NELEM(ssl_protocols), | |
9f48bbac | 162 | &test_ctx->expected_protocol, value); |
453dfd8d EK |
163 | } |
164 | ||
165 | const char *ssl_protocol_name(int protocol) | |
166 | { | |
167 | return enum_name(ssl_protocols, OSSL_NELEM(ssl_protocols), protocol); | |
168 | } | |
169 | ||
cc22cd54 | 170 | /* VerifyCallback */ |
a263f320 EK |
171 | |
172 | static const test_enum ssl_verify_callbacks[] = { | |
173 | {"None", SSL_TEST_VERIFY_NONE}, | |
174 | {"AcceptAll", SSL_TEST_VERIFY_ACCEPT_ALL}, | |
175 | {"RejectAll", SSL_TEST_VERIFY_REJECT_ALL}, | |
176 | }; | |
177 | ||
9f48bbac | 178 | __owur static int parse_client_verify_callback(SSL_TEST_CLIENT_CONF *client_conf, |
da085d27 | 179 | const char *value) |
a263f320 EK |
180 | { |
181 | int ret_value; | |
182 | if (!parse_enum(ssl_verify_callbacks, OSSL_NELEM(ssl_verify_callbacks), | |
183 | &ret_value, value)) { | |
184 | return 0; | |
185 | } | |
9f48bbac | 186 | client_conf->verify_callback = ret_value; |
a263f320 EK |
187 | return 1; |
188 | } | |
189 | ||
190 | const char *ssl_verify_callback_name(ssl_verify_callback_t callback) | |
191 | { | |
192 | return enum_name(ssl_verify_callbacks, OSSL_NELEM(ssl_verify_callbacks), | |
193 | callback); | |
194 | } | |
195 | ||
5c753de6 | 196 | /* ServerName */ |
5c753de6 TS |
197 | |
198 | static const test_enum ssl_servername[] = { | |
81fc33c9 | 199 | {"None", SSL_TEST_SERVERNAME_NONE}, |
5c753de6 TS |
200 | {"server1", SSL_TEST_SERVERNAME_SERVER1}, |
201 | {"server2", SSL_TEST_SERVERNAME_SERVER2}, | |
d2b23cd2 | 202 | {"invalid", SSL_TEST_SERVERNAME_INVALID}, |
5c753de6 TS |
203 | }; |
204 | ||
9f48bbac | 205 | __owur static int parse_servername(SSL_TEST_CLIENT_CONF *client_conf, |
5c753de6 TS |
206 | const char *value) |
207 | { | |
208 | int ret_value; | |
209 | if (!parse_enum(ssl_servername, OSSL_NELEM(ssl_servername), | |
210 | &ret_value, value)) { | |
211 | return 0; | |
212 | } | |
9f48bbac | 213 | client_conf->servername = ret_value; |
5c753de6 TS |
214 | return 1; |
215 | } | |
216 | ||
d2b23cd2 EK |
217 | __owur static int parse_expected_servername(SSL_TEST_CTX *test_ctx, |
218 | const char *value) | |
219 | { | |
220 | int ret_value; | |
221 | if (!parse_enum(ssl_servername, OSSL_NELEM(ssl_servername), | |
222 | &ret_value, value)) { | |
223 | return 0; | |
224 | } | |
225 | test_ctx->expected_servername = ret_value; | |
226 | return 1; | |
227 | } | |
228 | ||
5c753de6 TS |
229 | const char *ssl_servername_name(ssl_servername_t server) |
230 | { | |
231 | return enum_name(ssl_servername, OSSL_NELEM(ssl_servername), | |
232 | server); | |
233 | } | |
234 | ||
9f48bbac | 235 | /* ServerNameCallback */ |
d2b23cd2 EK |
236 | |
237 | static const test_enum ssl_servername_callbacks[] = { | |
238 | {"None", SSL_TEST_SERVERNAME_CB_NONE}, | |
239 | {"IgnoreMismatch", SSL_TEST_SERVERNAME_IGNORE_MISMATCH}, | |
240 | {"RejectMismatch", SSL_TEST_SERVERNAME_REJECT_MISMATCH}, | |
a9c0d8be DB |
241 | {"ClientHelloIgnoreMismatch", |
242 | SSL_TEST_SERVERNAME_CLIENT_HELLO_IGNORE_MISMATCH}, | |
243 | {"ClientHelloRejectMismatch", | |
244 | SSL_TEST_SERVERNAME_CLIENT_HELLO_REJECT_MISMATCH}, | |
245 | {"ClientHelloNoV12", SSL_TEST_SERVERNAME_CLIENT_HELLO_NO_V12}, | |
d2b23cd2 EK |
246 | }; |
247 | ||
9f48bbac EK |
248 | __owur static int parse_servername_callback(SSL_TEST_SERVER_CONF *server_conf, |
249 | const char *value) | |
d2b23cd2 EK |
250 | { |
251 | int ret_value; | |
252 | if (!parse_enum(ssl_servername_callbacks, | |
253 | OSSL_NELEM(ssl_servername_callbacks), &ret_value, value)) { | |
254 | return 0; | |
255 | } | |
9f48bbac | 256 | server_conf->servername_callback = ret_value; |
d2b23cd2 EK |
257 | return 1; |
258 | } | |
259 | ||
260 | const char *ssl_servername_callback_name(ssl_servername_callback_t callback) | |
261 | { | |
262 | return enum_name(ssl_servername_callbacks, | |
263 | OSSL_NELEM(ssl_servername_callbacks), callback); | |
264 | } | |
265 | ||
5c753de6 | 266 | /* SessionTicketExpected */ |
5c753de6 | 267 | |
81fc33c9 | 268 | static const test_enum ssl_session_ticket[] = { |
5c753de6 TS |
269 | {"Ignore", SSL_TEST_SESSION_TICKET_IGNORE}, |
270 | {"Yes", SSL_TEST_SESSION_TICKET_YES}, | |
271 | {"No", SSL_TEST_SESSION_TICKET_NO}, | |
5c753de6 TS |
272 | }; |
273 | ||
81fc33c9 | 274 | __owur static int parse_session_ticket(SSL_TEST_CTX *test_ctx, const char *value) |
5c753de6 TS |
275 | { |
276 | int ret_value; | |
81fc33c9 | 277 | if (!parse_enum(ssl_session_ticket, OSSL_NELEM(ssl_session_ticket), |
5c753de6 TS |
278 | &ret_value, value)) { |
279 | return 0; | |
280 | } | |
281 | test_ctx->session_ticket_expected = ret_value; | |
282 | return 1; | |
283 | } | |
284 | ||
81fc33c9 | 285 | const char *ssl_session_ticket_name(ssl_session_ticket_t server) |
5c753de6 | 286 | { |
81fc33c9 EK |
287 | return enum_name(ssl_session_ticket, |
288 | OSSL_NELEM(ssl_session_ticket), | |
5c753de6 TS |
289 | server); |
290 | } | |
453dfd8d | 291 | |
439db0c9 MC |
292 | /* CompressionExpected */ |
293 | ||
b6611753 | 294 | IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CTX, test, compression_expected) |
439db0c9 | 295 | |
a84e5c9a TS |
296 | /* SessionIdExpected */ |
297 | ||
298 | static const test_enum ssl_session_id[] = { | |
299 | {"Ignore", SSL_TEST_SESSION_ID_IGNORE}, | |
300 | {"Yes", SSL_TEST_SESSION_ID_YES}, | |
301 | {"No", SSL_TEST_SESSION_ID_NO}, | |
302 | }; | |
303 | ||
304 | __owur static int parse_session_id(SSL_TEST_CTX *test_ctx, const char *value) | |
305 | { | |
306 | int ret_value; | |
307 | if (!parse_enum(ssl_session_id, OSSL_NELEM(ssl_session_id), | |
308 | &ret_value, value)) { | |
309 | return 0; | |
310 | } | |
311 | test_ctx->session_id_expected = ret_value; | |
312 | return 1; | |
313 | } | |
314 | ||
315 | const char *ssl_session_id_name(ssl_session_id_t server) | |
316 | { | |
317 | return enum_name(ssl_session_id, | |
318 | OSSL_NELEM(ssl_session_id), | |
319 | server); | |
320 | } | |
321 | ||
cc22cd54 | 322 | /* Method */ |
74726750 EK |
323 | |
324 | static const test_enum ssl_test_methods[] = { | |
325 | {"TLS", SSL_TEST_METHOD_TLS}, | |
326 | {"DTLS", SSL_TEST_METHOD_DTLS}, | |
327 | }; | |
328 | ||
329 | __owur static int parse_test_method(SSL_TEST_CTX *test_ctx, const char *value) | |
330 | { | |
331 | int ret_value; | |
332 | if (!parse_enum(ssl_test_methods, OSSL_NELEM(ssl_test_methods), | |
333 | &ret_value, value)) { | |
334 | return 0; | |
335 | } | |
336 | test_ctx->method = ret_value; | |
337 | return 1; | |
338 | } | |
339 | ||
340 | const char *ssl_test_method_name(ssl_test_method_t method) | |
341 | { | |
342 | return enum_name(ssl_test_methods, OSSL_NELEM(ssl_test_methods), method); | |
343 | } | |
344 | ||
cc22cd54 | 345 | /* NPN and ALPN options */ |
ce2cdac2 | 346 | |
9f48bbac EK |
347 | IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, npn_protocols) |
348 | IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_SERVER_CONF, server, npn_protocols) | |
349 | IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CTX, test, expected_npn_protocol) | |
350 | IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, alpn_protocols) | |
351 | IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_SERVER_CONF, server, alpn_protocols) | |
352 | IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CTX, test, expected_alpn_protocol) | |
ce2cdac2 | 353 | |
ea1ecd98 EK |
354 | /* SRP options */ |
355 | IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, srp_user) | |
356 | IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_SERVER_CONF, server, srp_user) | |
357 | IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, srp_password) | |
358 | IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_SERVER_CONF, server, srp_password) | |
359 | ||
cc22cd54 | 360 | /* Handshake mode */ |
590ed3d7 EK |
361 | |
362 | static const test_enum ssl_handshake_modes[] = { | |
363 | {"Simple", SSL_TEST_HANDSHAKE_SIMPLE}, | |
364 | {"Resume", SSL_TEST_HANDSHAKE_RESUME}, | |
fe7dd553 MC |
365 | {"RenegotiateServer", SSL_TEST_HANDSHAKE_RENEG_SERVER}, |
366 | {"RenegotiateClient", SSL_TEST_HANDSHAKE_RENEG_CLIENT}, | |
9b92f161 MC |
367 | {"KeyUpdateServer", SSL_TEST_HANDSHAKE_KEY_UPDATE_SERVER}, |
368 | {"KeyUpdateClient", SSL_TEST_HANDSHAKE_KEY_UPDATE_CLIENT}, | |
590ed3d7 EK |
369 | }; |
370 | ||
371 | __owur static int parse_handshake_mode(SSL_TEST_CTX *test_ctx, const char *value) | |
372 | { | |
373 | int ret_value; | |
374 | if (!parse_enum(ssl_handshake_modes, OSSL_NELEM(ssl_handshake_modes), | |
375 | &ret_value, value)) { | |
376 | return 0; | |
377 | } | |
378 | test_ctx->handshake_mode = ret_value; | |
379 | return 1; | |
380 | } | |
381 | ||
382 | const char *ssl_handshake_mode_name(ssl_handshake_mode_t mode) | |
383 | { | |
384 | return enum_name(ssl_handshake_modes, OSSL_NELEM(ssl_handshake_modes), | |
385 | mode); | |
386 | } | |
387 | ||
cc22cd54 MC |
388 | /* Renegotiation Ciphersuites */ |
389 | ||
390 | IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, reneg_ciphers) | |
391 | ||
9b92f161 MC |
392 | /* KeyUpdateType */ |
393 | ||
394 | static const test_enum ssl_key_update_types[] = { | |
395 | {"KeyUpdateRequested", SSL_KEY_UPDATE_REQUESTED}, | |
396 | {"KeyUpdateNotRequested", SSL_KEY_UPDATE_NOT_REQUESTED}, | |
397 | }; | |
398 | ||
399 | __owur static int parse_key_update_type(SSL_TEST_CTX *test_ctx, const char *value) | |
400 | { | |
401 | int ret_value; | |
402 | if (!parse_enum(ssl_key_update_types, OSSL_NELEM(ssl_key_update_types), | |
403 | &ret_value, value)) { | |
404 | return 0; | |
405 | } | |
406 | test_ctx->key_update_type = ret_value; | |
407 | return 1; | |
408 | } | |
409 | ||
cc22cd54 | 410 | /* CT Validation */ |
da085d27 EK |
411 | |
412 | static const test_enum ssl_ct_validation_modes[] = { | |
413 | {"None", SSL_TEST_CT_VALIDATION_NONE}, | |
414 | {"Permissive", SSL_TEST_CT_VALIDATION_PERMISSIVE}, | |
415 | {"Strict", SSL_TEST_CT_VALIDATION_STRICT}, | |
416 | }; | |
417 | ||
418 | __owur static int parse_ct_validation(SSL_TEST_CLIENT_CONF *client_conf, | |
419 | const char *value) | |
420 | { | |
421 | int ret_value; | |
422 | if (!parse_enum(ssl_ct_validation_modes, OSSL_NELEM(ssl_ct_validation_modes), | |
423 | &ret_value, value)) { | |
424 | return 0; | |
425 | } | |
426 | client_conf->ct_validation = ret_value; | |
427 | return 1; | |
428 | } | |
429 | ||
430 | const char *ssl_ct_validation_name(ssl_ct_validation_t mode) | |
431 | { | |
432 | return enum_name(ssl_ct_validation_modes, OSSL_NELEM(ssl_ct_validation_modes), | |
433 | mode); | |
434 | } | |
435 | ||
9f48bbac EK |
436 | IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CTX, test, resumption_expected) |
437 | IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_SERVER_CONF, server, broken_session_ticket) | |
83964ca0 | 438 | IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CTX, test, use_sctp) |
590ed3d7 | 439 | |
767ccc3b | 440 | /* CertStatus */ |
767ccc3b MC |
441 | |
442 | static const test_enum ssl_certstatus[] = { | |
443 | {"None", SSL_TEST_CERT_STATUS_NONE}, | |
444 | {"GoodResponse", SSL_TEST_CERT_STATUS_GOOD_RESPONSE}, | |
445 | {"BadResponse", SSL_TEST_CERT_STATUS_BAD_RESPONSE} | |
446 | }; | |
447 | ||
448 | __owur static int parse_certstatus(SSL_TEST_SERVER_CONF *server_conf, | |
449 | const char *value) | |
450 | { | |
451 | int ret_value; | |
452 | if (!parse_enum(ssl_certstatus, OSSL_NELEM(ssl_certstatus), &ret_value, | |
453 | value)) { | |
454 | return 0; | |
455 | } | |
456 | server_conf->cert_status = ret_value; | |
457 | return 1; | |
458 | } | |
459 | ||
460 | const char *ssl_certstatus_name(ssl_cert_status_t cert_status) | |
461 | { | |
462 | return enum_name(ssl_certstatus, | |
463 | OSSL_NELEM(ssl_certstatus), cert_status); | |
464 | } | |
465 | ||
cc22cd54 | 466 | /* ApplicationData */ |
e0421bd8 EK |
467 | |
468 | IMPLEMENT_SSL_TEST_INT_OPTION(SSL_TEST_CTX, test, app_data_size) | |
469 | ||
cc22cd54 MC |
470 | |
471 | /* MaxFragmentSize */ | |
6dc99745 EK |
472 | |
473 | IMPLEMENT_SSL_TEST_INT_OPTION(SSL_TEST_CTX, test, max_fragment_size) | |
474 | ||
cf72c757 F |
475 | /* Maximum-Fragment-Length TLS extension mode */ |
476 | static const test_enum ssl_max_fragment_len_mode[] = { | |
477 | {"None", TLSEXT_max_fragment_length_DISABLED}, | |
478 | { "512", TLSEXT_max_fragment_length_512}, | |
479 | {"1024", TLSEXT_max_fragment_length_1024}, | |
480 | {"2048", TLSEXT_max_fragment_length_2048}, | |
481 | {"4096", TLSEXT_max_fragment_length_4096} | |
482 | }; | |
483 | ||
484 | __owur static int parse_max_fragment_len_mode(SSL_TEST_CLIENT_CONF *client_conf, | |
485 | const char *value) | |
486 | { | |
487 | int ret_value; | |
488 | ||
489 | if (!parse_enum(ssl_max_fragment_len_mode, | |
490 | OSSL_NELEM(ssl_max_fragment_len_mode), &ret_value, value)) { | |
491 | return 0; | |
492 | } | |
493 | client_conf->max_fragment_len_mode = ret_value; | |
494 | return 1; | |
495 | } | |
496 | ||
497 | const char *ssl_max_fragment_len_name(int MFL_mode) | |
498 | { | |
499 | return enum_name(ssl_max_fragment_len_mode, | |
500 | OSSL_NELEM(ssl_max_fragment_len_mode), MFL_mode); | |
501 | } | |
502 | ||
cc22cd54 MC |
503 | |
504 | /* Expected key and signature types */ | |
b93ad05d | 505 | |
7f5f35af | 506 | __owur static int parse_expected_key_type(int *ptype, const char *value) |
b93ad05d DSH |
507 | { |
508 | int nid; | |
7f5f35af | 509 | const EVP_PKEY_ASN1_METHOD *ameth; |
b93ad05d DSH |
510 | |
511 | if (value == NULL) | |
512 | return 0; | |
7f5f35af DSH |
513 | ameth = EVP_PKEY_asn1_find_str(NULL, value, -1); |
514 | if (ameth != NULL) | |
515 | EVP_PKEY_asn1_get0_info(&nid, NULL, NULL, NULL, NULL, ameth); | |
516 | else | |
517 | nid = OBJ_sn2nid(value); | |
b93ad05d DSH |
518 | if (nid == NID_undef) |
519 | nid = OBJ_ln2nid(value); | |
520 | #ifndef OPENSSL_NO_EC | |
521 | if (nid == NID_undef) | |
522 | nid = EC_curve_nist2nid(value); | |
523 | #endif | |
524 | if (nid == NID_undef) | |
525 | return 0; | |
7f5f35af | 526 | *ptype = nid; |
b93ad05d DSH |
527 | return 1; |
528 | } | |
529 | ||
7f5f35af DSH |
530 | __owur static int parse_expected_tmp_key_type(SSL_TEST_CTX *test_ctx, |
531 | const char *value) | |
532 | { | |
533 | return parse_expected_key_type(&test_ctx->expected_tmp_key_type, value); | |
534 | } | |
535 | ||
536 | __owur static int parse_expected_server_cert_type(SSL_TEST_CTX *test_ctx, | |
537 | const char *value) | |
538 | { | |
539 | return parse_expected_key_type(&test_ctx->expected_server_cert_type, | |
540 | value); | |
541 | } | |
542 | ||
54b7f2a5 DSH |
543 | __owur static int parse_expected_server_sign_type(SSL_TEST_CTX *test_ctx, |
544 | const char *value) | |
545 | { | |
546 | return parse_expected_key_type(&test_ctx->expected_server_sign_type, | |
547 | value); | |
548 | } | |
549 | ||
7f5f35af DSH |
550 | __owur static int parse_expected_client_cert_type(SSL_TEST_CTX *test_ctx, |
551 | const char *value) | |
552 | { | |
553 | return parse_expected_key_type(&test_ctx->expected_client_cert_type, | |
554 | value); | |
555 | } | |
556 | ||
54b7f2a5 DSH |
557 | __owur static int parse_expected_client_sign_type(SSL_TEST_CTX *test_ctx, |
558 | const char *value) | |
559 | { | |
560 | return parse_expected_key_type(&test_ctx->expected_client_sign_type, | |
561 | value); | |
562 | } | |
563 | ||
cc22cd54 | 564 | |
ee5b6a42 | 565 | /* Expected signing hash */ |
ee5b6a42 DSH |
566 | |
567 | __owur static int parse_expected_sign_hash(int *ptype, const char *value) | |
568 | { | |
569 | int nid; | |
570 | ||
571 | if (value == NULL) | |
572 | return 0; | |
573 | nid = OBJ_sn2nid(value); | |
574 | if (nid == NID_undef) | |
575 | nid = OBJ_ln2nid(value); | |
576 | if (nid == NID_undef) | |
577 | return 0; | |
578 | *ptype = nid; | |
579 | return 1; | |
580 | } | |
581 | ||
582 | __owur static int parse_expected_server_sign_hash(SSL_TEST_CTX *test_ctx, | |
583 | const char *value) | |
584 | { | |
585 | return parse_expected_sign_hash(&test_ctx->expected_server_sign_hash, | |
586 | value); | |
587 | } | |
588 | ||
589 | __owur static int parse_expected_client_sign_hash(SSL_TEST_CTX *test_ctx, | |
590 | const char *value) | |
591 | { | |
4bb0b438 | 592 | return parse_expected_sign_hash(&test_ctx->expected_client_sign_hash, |
ee5b6a42 DSH |
593 | value); |
594 | } | |
595 | ||
2e21539b DSH |
596 | __owur static int parse_expected_ca_names(STACK_OF(X509_NAME) **pnames, |
597 | const char *value) | |
598 | { | |
599 | if (value == NULL) | |
600 | return 0; | |
601 | if (!strcmp(value, "empty")) | |
602 | *pnames = sk_X509_NAME_new_null(); | |
603 | else | |
604 | *pnames = SSL_load_client_CA_file(value); | |
605 | return *pnames != NULL; | |
606 | } | |
f15b50c4 DSH |
607 | __owur static int parse_expected_server_ca_names(SSL_TEST_CTX *test_ctx, |
608 | const char *value) | |
609 | { | |
610 | return parse_expected_ca_names(&test_ctx->expected_server_ca_names, value); | |
611 | } | |
2e21539b DSH |
612 | __owur static int parse_expected_client_ca_names(SSL_TEST_CTX *test_ctx, |
613 | const char *value) | |
614 | { | |
615 | return parse_expected_ca_names(&test_ctx->expected_client_ca_names, value); | |
616 | } | |
cc22cd54 | 617 | |
e1c7871d TS |
618 | /* ExpectedCipher */ |
619 | ||
620 | IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CTX, test, expected_cipher) | |
621 | ||
453dfd8d | 622 | /* Known test options and their corresponding parse methods. */ |
453dfd8d | 623 | |
9f48bbac | 624 | /* Top-level options. */ |
453dfd8d EK |
625 | typedef struct { |
626 | const char *name; | |
627 | int (*parse)(SSL_TEST_CTX *test_ctx, const char *value); | |
628 | } ssl_test_ctx_option; | |
629 | ||
630 | static const ssl_test_ctx_option ssl_test_ctx_options[] = { | |
631 | { "ExpectedResult", &parse_expected_result }, | |
9f48bbac EK |
632 | { "ExpectedClientAlert", &parse_client_alert }, |
633 | { "ExpectedServerAlert", &parse_server_alert }, | |
634 | { "ExpectedProtocol", &parse_protocol }, | |
d2b23cd2 | 635 | { "ExpectedServerName", &parse_expected_servername }, |
81fc33c9 | 636 | { "SessionTicketExpected", &parse_session_ticket }, |
b6611753 | 637 | { "CompressionExpected", &parse_test_compression_expected }, |
a84e5c9a | 638 | { "SessionIdExpected", &parse_session_id }, |
74726750 | 639 | { "Method", &parse_test_method }, |
9f48bbac EK |
640 | { "ExpectedNPNProtocol", &parse_test_expected_npn_protocol }, |
641 | { "ExpectedALPNProtocol", &parse_test_expected_alpn_protocol }, | |
590ed3d7 | 642 | { "HandshakeMode", &parse_handshake_mode }, |
9b92f161 | 643 | { "KeyUpdateType", &parse_key_update_type }, |
9f48bbac | 644 | { "ResumptionExpected", &parse_test_resumption_expected }, |
e0421bd8 | 645 | { "ApplicationData", &parse_test_app_data_size }, |
6dc99745 | 646 | { "MaxFragmentSize", &parse_test_max_fragment_size }, |
b93ad05d | 647 | { "ExpectedTmpKeyType", &parse_expected_tmp_key_type }, |
7f5f35af | 648 | { "ExpectedServerCertType", &parse_expected_server_cert_type }, |
ee5b6a42 | 649 | { "ExpectedServerSignHash", &parse_expected_server_sign_hash }, |
54b7f2a5 | 650 | { "ExpectedServerSignType", &parse_expected_server_sign_type }, |
f15b50c4 | 651 | { "ExpectedServerCANames", &parse_expected_server_ca_names }, |
7f5f35af | 652 | { "ExpectedClientCertType", &parse_expected_client_cert_type }, |
ee5b6a42 | 653 | { "ExpectedClientSignHash", &parse_expected_client_sign_hash }, |
54b7f2a5 | 654 | { "ExpectedClientSignType", &parse_expected_client_sign_type }, |
2e21539b | 655 | { "ExpectedClientCANames", &parse_expected_client_ca_names }, |
83964ca0 | 656 | { "UseSCTP", &parse_test_use_sctp }, |
e1c7871d | 657 | { "ExpectedCipher", &parse_test_expected_cipher }, |
9f48bbac EK |
658 | }; |
659 | ||
660 | /* Nested client options. */ | |
661 | typedef struct { | |
662 | const char *name; | |
663 | int (*parse)(SSL_TEST_CLIENT_CONF *conf, const char *value); | |
664 | } ssl_test_client_option; | |
665 | ||
666 | static const ssl_test_client_option ssl_test_client_options[] = { | |
667 | { "VerifyCallback", &parse_client_verify_callback }, | |
668 | { "ServerName", &parse_servername }, | |
669 | { "NPNProtocols", &parse_client_npn_protocols }, | |
670 | { "ALPNProtocols", &parse_client_alpn_protocols }, | |
da085d27 | 671 | { "CTValidation", &parse_ct_validation }, |
cc22cd54 | 672 | { "RenegotiateCiphers", &parse_client_reneg_ciphers}, |
ea1ecd98 EK |
673 | { "SRPUser", &parse_client_srp_user }, |
674 | { "SRPPassword", &parse_client_srp_password }, | |
cf72c757 | 675 | { "MaxFragmentLenExt", &parse_max_fragment_len_mode }, |
9f48bbac EK |
676 | }; |
677 | ||
678 | /* Nested server options. */ | |
679 | typedef struct { | |
680 | const char *name; | |
681 | int (*parse)(SSL_TEST_SERVER_CONF *conf, const char *value); | |
682 | } ssl_test_server_option; | |
683 | ||
684 | static const ssl_test_server_option ssl_test_server_options[] = { | |
685 | { "ServerNameCallback", &parse_servername_callback }, | |
686 | { "NPNProtocols", &parse_server_npn_protocols }, | |
687 | { "ALPNProtocols", &parse_server_alpn_protocols }, | |
688 | { "BrokenSessionTicket", &parse_server_broken_session_ticket }, | |
767ccc3b | 689 | { "CertStatus", &parse_certstatus }, |
ea1ecd98 EK |
690 | { "SRPUser", &parse_server_srp_user }, |
691 | { "SRPPassword", &parse_server_srp_password }, | |
453dfd8d EK |
692 | }; |
693 | ||
453dfd8d EK |
694 | SSL_TEST_CTX *SSL_TEST_CTX_new() |
695 | { | |
696 | SSL_TEST_CTX *ret; | |
019e47ce P |
697 | |
698 | /* The return code is checked by caller */ | |
699 | if ((ret = OPENSSL_zalloc(sizeof(*ret))) != NULL) { | |
700 | ret->app_data_size = default_app_data_size; | |
701 | ret->max_fragment_size = default_max_fragment_size; | |
702 | } | |
453dfd8d EK |
703 | return ret; |
704 | } | |
705 | ||
9f48bbac EK |
706 | static void ssl_test_extra_conf_free_data(SSL_TEST_EXTRA_CONF *conf) |
707 | { | |
708 | OPENSSL_free(conf->client.npn_protocols); | |
709 | OPENSSL_free(conf->server.npn_protocols); | |
710 | OPENSSL_free(conf->server2.npn_protocols); | |
711 | OPENSSL_free(conf->client.alpn_protocols); | |
712 | OPENSSL_free(conf->server.alpn_protocols); | |
713 | OPENSSL_free(conf->server2.alpn_protocols); | |
d605fc3a | 714 | OPENSSL_free(conf->client.reneg_ciphers); |
ea1ecd98 EK |
715 | OPENSSL_free(conf->server.srp_user); |
716 | OPENSSL_free(conf->server.srp_password); | |
717 | OPENSSL_free(conf->server2.srp_user); | |
718 | OPENSSL_free(conf->server2.srp_password); | |
719 | OPENSSL_free(conf->client.srp_user); | |
720 | OPENSSL_free(conf->client.srp_password); | |
9f48bbac EK |
721 | } |
722 | ||
723 | static void ssl_test_ctx_free_extra_data(SSL_TEST_CTX *ctx) | |
453dfd8d | 724 | { |
9f48bbac EK |
725 | ssl_test_extra_conf_free_data(&ctx->extra); |
726 | ssl_test_extra_conf_free_data(&ctx->resume_extra); | |
727 | } | |
ce2cdac2 | 728 | |
9f48bbac EK |
729 | void SSL_TEST_CTX_free(SSL_TEST_CTX *ctx) |
730 | { | |
731 | ssl_test_ctx_free_extra_data(ctx); | |
ce2cdac2 EK |
732 | OPENSSL_free(ctx->expected_npn_protocol); |
733 | OPENSSL_free(ctx->expected_alpn_protocol); | |
f15b50c4 | 734 | sk_X509_NAME_pop_free(ctx->expected_server_ca_names, X509_NAME_free); |
2e21539b | 735 | sk_X509_NAME_pop_free(ctx->expected_client_ca_names, X509_NAME_free); |
e1c7871d | 736 | OPENSSL_free(ctx->expected_cipher); |
453dfd8d EK |
737 | OPENSSL_free(ctx); |
738 | } | |
739 | ||
9f48bbac EK |
740 | static int parse_client_options(SSL_TEST_CLIENT_CONF *client, const CONF *conf, |
741 | const char *client_section) | |
453dfd8d EK |
742 | { |
743 | STACK_OF(CONF_VALUE) *sk_conf; | |
453dfd8d EK |
744 | int i; |
745 | size_t j; | |
746 | ||
019e47ce P |
747 | if (!TEST_ptr(sk_conf = NCONF_get_section(conf, client_section))) |
748 | return 0; | |
453dfd8d | 749 | |
9f48bbac EK |
750 | for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) { |
751 | int found = 0; | |
752 | const CONF_VALUE *option = sk_CONF_VALUE_value(sk_conf, i); | |
753 | for (j = 0; j < OSSL_NELEM(ssl_test_client_options); j++) { | |
754 | if (strcmp(option->name, ssl_test_client_options[j].name) == 0) { | |
755 | if (!ssl_test_client_options[j].parse(client, option->value)) { | |
8fe3127c P |
756 | TEST_info("Bad value %s for option %s", |
757 | option->value, option->name); | |
9f48bbac EK |
758 | return 0; |
759 | } | |
760 | found = 1; | |
761 | break; | |
762 | } | |
763 | } | |
764 | if (!found) { | |
8fe3127c | 765 | TEST_info("Unknown test option: %s", option->name); |
9f48bbac EK |
766 | return 0; |
767 | } | |
768 | } | |
769 | ||
770 | return 1; | |
771 | } | |
772 | ||
773 | static int parse_server_options(SSL_TEST_SERVER_CONF *server, const CONF *conf, | |
774 | const char *server_section) | |
775 | { | |
776 | STACK_OF(CONF_VALUE) *sk_conf; | |
777 | int i; | |
778 | size_t j; | |
779 | ||
019e47ce P |
780 | if (!TEST_ptr(sk_conf = NCONF_get_section(conf, server_section))) |
781 | return 0; | |
453dfd8d EK |
782 | |
783 | for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) { | |
784 | int found = 0; | |
785 | const CONF_VALUE *option = sk_CONF_VALUE_value(sk_conf, i); | |
9f48bbac EK |
786 | for (j = 0; j < OSSL_NELEM(ssl_test_server_options); j++) { |
787 | if (strcmp(option->name, ssl_test_server_options[j].name) == 0) { | |
788 | if (!ssl_test_server_options[j].parse(server, option->value)) { | |
8fe3127c P |
789 | TEST_info("Bad value %s for option %s", |
790 | option->value, option->name); | |
9f48bbac | 791 | return 0; |
453dfd8d EK |
792 | } |
793 | found = 1; | |
794 | break; | |
795 | } | |
796 | } | |
797 | if (!found) { | |
8fe3127c | 798 | TEST_info("Unknown test option: %s", option->name); |
9f48bbac EK |
799 | return 0; |
800 | } | |
801 | } | |
802 | ||
803 | return 1; | |
804 | } | |
805 | ||
806 | SSL_TEST_CTX *SSL_TEST_CTX_create(const CONF *conf, const char *test_section) | |
807 | { | |
019e47ce P |
808 | STACK_OF(CONF_VALUE) *sk_conf = NULL; |
809 | SSL_TEST_CTX *ctx = NULL; | |
9f48bbac EK |
810 | int i; |
811 | size_t j; | |
812 | ||
019e47ce P |
813 | if (!TEST_ptr(sk_conf = NCONF_get_section(conf, test_section)) |
814 | || !TEST_ptr(ctx = SSL_TEST_CTX_new())) | |
815 | goto err; | |
9f48bbac EK |
816 | |
817 | for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) { | |
818 | int found = 0; | |
819 | const CONF_VALUE *option = sk_CONF_VALUE_value(sk_conf, i); | |
820 | ||
821 | /* Subsections */ | |
822 | if (strcmp(option->name, "client") == 0) { | |
045fe731 | 823 | if (!parse_client_options(&ctx->extra.client, conf, option->value)) |
9f48bbac EK |
824 | goto err; |
825 | } else if (strcmp(option->name, "server") == 0) { | |
045fe731 | 826 | if (!parse_server_options(&ctx->extra.server, conf, option->value)) |
9f48bbac EK |
827 | goto err; |
828 | } else if (strcmp(option->name, "server2") == 0) { | |
045fe731 | 829 | if (!parse_server_options(&ctx->extra.server2, conf, option->value)) |
9f48bbac EK |
830 | goto err; |
831 | } else if (strcmp(option->name, "resume-client") == 0) { | |
045fe731 P |
832 | if (!parse_client_options(&ctx->resume_extra.client, conf, |
833 | option->value)) | |
9f48bbac EK |
834 | goto err; |
835 | } else if (strcmp(option->name, "resume-server") == 0) { | |
045fe731 P |
836 | if (!parse_server_options(&ctx->resume_extra.server, conf, |
837 | option->value)) | |
9f48bbac EK |
838 | goto err; |
839 | } else if (strcmp(option->name, "resume-server2") == 0) { | |
840 | if (!parse_server_options(&ctx->resume_extra.server2, conf, | |
841 | option->value)) | |
842 | goto err; | |
9f48bbac EK |
843 | } else { |
844 | for (j = 0; j < OSSL_NELEM(ssl_test_ctx_options); j++) { | |
845 | if (strcmp(option->name, ssl_test_ctx_options[j].name) == 0) { | |
846 | if (!ssl_test_ctx_options[j].parse(ctx, option->value)) { | |
8fe3127c P |
847 | TEST_info("Bad value %s for option %s", |
848 | option->value, option->name); | |
9f48bbac EK |
849 | goto err; |
850 | } | |
851 | found = 1; | |
852 | break; | |
853 | } | |
854 | } | |
855 | if (!found) { | |
8fe3127c | 856 | TEST_info("Unknown test option: %s", option->name); |
9f48bbac EK |
857 | goto err; |
858 | } | |
453dfd8d EK |
859 | } |
860 | } | |
861 | ||
862 | goto done; | |
863 | ||
864 | err: | |
865 | SSL_TEST_CTX_free(ctx); | |
866 | ctx = NULL; | |
867 | done: | |
868 | return ctx; | |
869 | } |