summaryrefslogtreecommitdiff
path: root/src/regress/lib/libssl/unit/ssl_get_shared_ciphers.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/regress/lib/libssl/unit/ssl_get_shared_ciphers.c')
-rw-r--r--src/regress/lib/libssl/unit/ssl_get_shared_ciphers.c478
1 files changed, 0 insertions, 478 deletions
diff --git a/src/regress/lib/libssl/unit/ssl_get_shared_ciphers.c b/src/regress/lib/libssl/unit/ssl_get_shared_ciphers.c
deleted file mode 100644
index e26f614e53..0000000000
--- a/src/regress/lib/libssl/unit/ssl_get_shared_ciphers.c
+++ /dev/null
@@ -1,478 +0,0 @@
1/* $OpenBSD: ssl_get_shared_ciphers.c,v 1.13 2024/08/31 12:47:24 jsing Exp $ */
2/*
3 * Copyright (c) 2021 Theo Buehler <tb@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <stdint.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
23#include <openssl/bio.h>
24#include <openssl/crypto.h>
25#include <openssl/err.h>
26#include <openssl/ssl.h>
27
28struct peer_config {
29 const char *name;
30 int server;
31 uint16_t max_version;
32 uint16_t min_version;
33 const char *ciphers;
34};
35
36struct ssl_shared_ciphers_test_data {
37 const char *description;
38 struct peer_config client_config;
39 struct peer_config server_config;
40 const char *shared_ciphers;
41 const char *shared_ciphers_without_aesni;
42};
43
44char *server_cert;
45char *server_key;
46
47static const struct ssl_shared_ciphers_test_data ssl_shared_ciphers_tests[] = {
48 {
49 .description = "TLSv1.3 defaults",
50 .client_config = {
51 .name = "client",
52 .server = 0,
53 .max_version = TLS1_3_VERSION,
54 .min_version = TLS1_3_VERSION,
55 .ciphers =
56 "TLS_AES_256_GCM_SHA384:"
57 "TLS_CHACHA20_POLY1305_SHA256:"
58 "TLS_AES_128_GCM_SHA256",
59 },
60 .server_config = {
61 .name = "server",
62 .server = 1,
63 .max_version = TLS1_3_VERSION,
64 .min_version = TLS1_3_VERSION,
65 .ciphers =
66 "TLS_AES_256_GCM_SHA384:"
67 "TLS_CHACHA20_POLY1305_SHA256:"
68 "TLS_AES_128_GCM_SHA256",
69 },
70 .shared_ciphers =
71 "TLS_AES_256_GCM_SHA384:"
72 "TLS_CHACHA20_POLY1305_SHA256:"
73 "TLS_AES_128_GCM_SHA256",
74 },
75
76 {
77 .description = "TLSv1.3, client without ChaCha",
78 .client_config = {
79 .name = "client",
80 .server = 0,
81 .max_version = TLS1_3_VERSION,
82 .min_version = TLS1_3_VERSION,
83 .ciphers =
84 "TLS_AES_256_GCM_SHA384:"
85 "TLS_AES_128_GCM_SHA256",
86 },
87 .server_config = {
88 .name = "server",
89 .server = 1,
90 .max_version = TLS1_3_VERSION,
91 .min_version = TLS1_3_VERSION,
92 .ciphers =
93 "TLS_AES_256_GCM_SHA384:"
94 "TLS_CHACHA20_POLY1305_SHA256:"
95 "TLS_AES_128_GCM_SHA256",
96 },
97 .shared_ciphers =
98 "TLS_AES_256_GCM_SHA384:"
99 "TLS_AES_128_GCM_SHA256",
100 },
101
102 {
103 .description = "TLSv1.2",
104 .client_config = {
105 .name = "client",
106 .server = 0,
107 .max_version = TLS1_2_VERSION,
108 .min_version = TLS1_2_VERSION,
109 .ciphers =
110 "ECDHE-RSA-AES256-GCM-SHA384:"
111 "ECDHE-ECDSA-AES256-GCM-SHA384:"
112 "ECDHE-RSA-AES256-SHA384:"
113 "ECDHE-ECDSA-AES256-SHA384:"
114 "ECDHE-RSA-AES256-SHA:"
115 "ECDHE-ECDSA-AES256-SHA",
116 },
117 .server_config = {
118 .name = "server",
119 .server = 1,
120 .max_version = TLS1_2_VERSION,
121 .min_version = TLS1_2_VERSION,
122 .ciphers =
123 "ECDHE-RSA-AES256-GCM-SHA384:"
124 "ECDHE-ECDSA-AES256-GCM-SHA384:"
125 "ECDHE-RSA-AES256-SHA384:"
126 "ECDHE-ECDSA-AES256-SHA384:"
127 "ECDHE-RSA-AES256-SHA:"
128 "ECDHE-ECDSA-AES256-SHA",
129 },
130 .shared_ciphers =
131 "ECDHE-RSA-AES256-GCM-SHA384:"
132 "ECDHE-ECDSA-AES256-GCM-SHA384:"
133 "ECDHE-RSA-AES256-SHA384:"
134 "ECDHE-ECDSA-AES256-SHA384:"
135 "ECDHE-RSA-AES256-SHA:"
136 "ECDHE-ECDSA-AES256-SHA",
137 },
138
139 {
140 .description = "TLSv1.2, server without ECDSA",
141 .client_config = {
142 .name = "client",
143 .server = 0,
144 .max_version = TLS1_2_VERSION,
145 .min_version = TLS1_2_VERSION,
146 .ciphers =
147 "ECDHE-RSA-AES256-GCM-SHA384:"
148 "ECDHE-ECDSA-AES256-GCM-SHA384:"
149 "ECDHE-RSA-AES256-SHA384:"
150 "ECDHE-ECDSA-AES256-SHA384:"
151 "ECDHE-RSA-AES256-SHA:"
152 "ECDHE-ECDSA-AES256-SHA",
153 },
154 .server_config = {
155 .name = "server",
156 .server = 1,
157 .max_version = TLS1_2_VERSION,
158 .min_version = TLS1_2_VERSION,
159 .ciphers =
160 "ECDHE-RSA-AES256-GCM-SHA384:"
161 "ECDHE-RSA-AES256-SHA384:"
162 "ECDHE-RSA-AES256-SHA",
163 },
164 .shared_ciphers =
165 "ECDHE-RSA-AES256-GCM-SHA384:"
166 "ECDHE-RSA-AES256-SHA384:"
167 "ECDHE-RSA-AES256-SHA",
168 },
169
170 {
171 .description = "TLSv1.3 ciphers are prepended",
172 .client_config = {
173 .name = "client",
174 .server = 0,
175 .max_version = TLS1_3_VERSION,
176 .min_version = TLS1_2_VERSION,
177 .ciphers =
178 "ECDHE-RSA-AES256-GCM-SHA384",
179 },
180 .server_config = {
181 .name = "server",
182 .server = 1,
183 .max_version = TLS1_3_VERSION,
184 .min_version = TLS1_2_VERSION,
185 .ciphers =
186 "ECDHE-RSA-AES256-GCM-SHA384",
187 },
188 .shared_ciphers =
189 "TLS_AES_256_GCM_SHA384:"
190 "TLS_CHACHA20_POLY1305_SHA256:"
191 "TLS_AES_128_GCM_SHA256:"
192 "ECDHE-RSA-AES256-GCM-SHA384",
193 .shared_ciphers_without_aesni =
194 "TLS_CHACHA20_POLY1305_SHA256:"
195 "TLS_AES_256_GCM_SHA384:"
196 "TLS_AES_128_GCM_SHA256:"
197 "ECDHE-RSA-AES256-GCM-SHA384",
198 },
199};
200
201static const size_t N_SHARED_CIPHERS_TESTS =
202 sizeof(ssl_shared_ciphers_tests) / sizeof(ssl_shared_ciphers_tests[0]);
203
204static SSL_CTX *
205peer_config_to_ssl_ctx(const struct peer_config *config)
206{
207 SSL_CTX *ctx;
208
209 if ((ctx = SSL_CTX_new(TLS_method())) == NULL) {
210 fprintf(stderr, "SSL_CTX_new(%s) failed\n", config->name);
211 goto err;
212 }
213 if (!SSL_CTX_set_max_proto_version(ctx, config->max_version)) {
214 fprintf(stderr, "max_proto_version(%s) failed\n", config->name);
215 goto err;
216 }
217 if (!SSL_CTX_set_min_proto_version(ctx, config->min_version)) {
218 fprintf(stderr, "min_proto_version(%s) failed\n", config->name);
219 goto err;
220 }
221 if (!SSL_CTX_set_cipher_list(ctx, config->ciphers)) {
222 fprintf(stderr, "set_cipher_list(%s) failed\n", config->name);
223 goto err;
224 }
225
226 if (config->server) {
227 if (!SSL_CTX_use_certificate_file(ctx, server_cert,
228 SSL_FILETYPE_PEM)) {
229 fprintf(stderr, "use_certificate_file(%s) failed\n",
230 config->name);
231 goto err;
232 }
233 if (!SSL_CTX_use_PrivateKey_file(ctx, server_key,
234 SSL_FILETYPE_PEM)) {
235 fprintf(stderr, "use_PrivateKey_file(%s) failed\n",
236 config->name);
237 goto err;
238 }
239 }
240
241 return ctx;
242
243 err:
244 SSL_CTX_free(ctx);
245 return NULL;
246}
247
248/* Connect client and server via a pair of "nonblocking" memory BIOs. */
249static int
250connect_peers(SSL *client_ssl, SSL *server_ssl, const char *description)
251{
252 BIO *client_wbio = NULL, *server_wbio = NULL;
253 int ret = 0;
254
255 if ((client_wbio = BIO_new(BIO_s_mem())) == NULL) {
256 fprintf(stderr, "%s: failed to create client BIO\n",
257 description);
258 goto err;
259 }
260 if ((server_wbio = BIO_new(BIO_s_mem())) == NULL) {
261 fprintf(stderr, "%s: failed to create server BIO\n",
262 description);
263 goto err;
264 }
265 if (BIO_set_mem_eof_return(client_wbio, -1) <= 0) {
266 fprintf(stderr, "%s: failed to set client eof return\n",
267 description);
268 goto err;
269 }
270 if (BIO_set_mem_eof_return(server_wbio, -1) <= 0) {
271 fprintf(stderr, "%s: failed to set server eof return\n",
272 description);
273 goto err;
274 }
275
276 /* Avoid double free. SSL_set_bio() takes ownership of the BIOs. */
277 BIO_up_ref(client_wbio);
278 BIO_up_ref(server_wbio);
279
280 SSL_set_bio(client_ssl, server_wbio, client_wbio);
281 SSL_set_bio(server_ssl, client_wbio, server_wbio);
282 client_wbio = NULL;
283 server_wbio = NULL;
284
285 ret = 1;
286
287 err:
288 BIO_free(client_wbio);
289 BIO_free(server_wbio);
290
291 return ret;
292}
293
294static int
295push_data_to_peer(SSL *ssl, int *ret, int (*func)(SSL *), const char *func_name,
296 const char *description)
297{
298 int ssl_err = 0;
299
300 if (*ret == 1)
301 return 1;
302
303 /*
304 * Do SSL_connect/SSL_accept/SSL_shutdown once and loop while hitting
305 * WANT_WRITE. If done or on WANT_READ hand off to peer.
306 */
307
308 do {
309 if ((*ret = func(ssl)) <= 0)
310 ssl_err = SSL_get_error(ssl, *ret);
311 } while (*ret <= 0 && ssl_err == SSL_ERROR_WANT_WRITE);
312
313 /* Ignore erroneous error - see SSL_shutdown(3)... */
314 if (func == SSL_shutdown && ssl_err == SSL_ERROR_SYSCALL)
315 return 1;
316
317 if (*ret <= 0 && ssl_err != SSL_ERROR_WANT_READ) {
318 fprintf(stderr, "%s: %s failed\n", description, func_name);
319 ERR_print_errors_fp(stderr);
320 return 0;
321 }
322
323 return 1;
324}
325
326/*
327 * Alternate between loops of SSL_connect() and SSL_accept() as long as only
328 * WANT_READ and WANT_WRITE situations are encountered. A function is repeated
329 * until WANT_READ is returned or it succeeds, then it's the other function's
330 * turn to make progress. Succeeds if SSL_connect() and SSL_accept() return 1.
331 */
332static int
333handshake(SSL *client_ssl, SSL *server_ssl, const char *description)
334{
335 int loops = 0, client_ret = 0, server_ret = 0;
336
337 while (loops++ < 10 && (client_ret <= 0 || server_ret <= 0)) {
338 if (!push_data_to_peer(client_ssl, &client_ret, SSL_connect,
339 "SSL_connect", description))
340 return 0;
341
342 if (!push_data_to_peer(server_ssl, &server_ret, SSL_accept,
343 "SSL_accept", description))
344 return 0;
345 }
346
347 if (client_ret != 1 || server_ret != 1) {
348 fprintf(stderr, "%s: failed\n", __func__);
349 return 0;
350 }
351
352 return 1;
353}
354
355static int
356shutdown_peers(SSL *client_ssl, SSL *server_ssl, const char *description)
357{
358 int loops = 0, client_ret = 0, server_ret = 0;
359
360 while (loops++ < 10 && (client_ret <= 0 || server_ret <= 0)) {
361 if (!push_data_to_peer(client_ssl, &client_ret, SSL_shutdown,
362 "client shutdown", description))
363 return 0;
364
365 if (!push_data_to_peer(server_ssl, &server_ret, SSL_shutdown,
366 "server shutdown", description))
367 return 0;
368 }
369
370 if (client_ret != 1 || server_ret != 1) {
371 fprintf(stderr, "%s: failed\n", __func__);
372 return 0;
373 }
374
375 return 1;
376}
377
378/* from ssl_ciph.c */
379static inline int
380ssl_aes_is_accelerated(void)
381{
382 return (OPENSSL_cpu_caps() & CRYPTO_CPU_CAPS_ACCELERATED_AES) != 0;
383}
384
385static int
386check_shared_ciphers(const struct ssl_shared_ciphers_test_data *test,
387 const char *got)
388{
389 const char *want = test->shared_ciphers;
390 int failed;
391
392 if (!ssl_aes_is_accelerated() &&
393 test->shared_ciphers_without_aesni != NULL)
394 want = test->shared_ciphers_without_aesni;
395
396 failed = strcmp(want, got);
397
398 if (failed)
399 fprintf(stderr, "%s: want \"%s\", got \"%s\"\n",
400 test->description, want, got);
401
402 return failed;
403}
404
405static int
406test_get_shared_ciphers(const struct ssl_shared_ciphers_test_data *test)
407{
408 SSL_CTX *client_ctx = NULL, *server_ctx = NULL;
409 SSL *client_ssl = NULL, *server_ssl = NULL;
410 char buf[4096];
411 int failed = 1;
412
413 if ((client_ctx = peer_config_to_ssl_ctx(&test->client_config)) == NULL)
414 goto err;
415 if ((server_ctx = peer_config_to_ssl_ctx(&test->server_config)) == NULL)
416 goto err;
417
418 if ((client_ssl = SSL_new(client_ctx)) == NULL) {
419 fprintf(stderr, "%s: failed to create client SSL\n",
420 test->description);
421 goto err;
422 }
423 if ((server_ssl = SSL_new(server_ctx)) == NULL) {
424 fprintf(stderr, "%s: failed to create server SSL\n",
425 test->description);
426 goto err;
427 }
428
429 if (!connect_peers(client_ssl, server_ssl, test->description))
430 goto err;
431
432 if (!handshake(client_ssl, server_ssl, test->description))
433 goto err;
434
435 if (SSL_get_shared_ciphers(server_ssl, buf, sizeof(buf)) == NULL) {
436 fprintf(stderr, "%s: failed to get shared ciphers\n",
437 test->description);
438 goto err;
439 }
440
441 if (!shutdown_peers(client_ssl, server_ssl, test->description))
442 goto err;
443
444 failed = check_shared_ciphers(test, buf);
445
446 err:
447 SSL_CTX_free(client_ctx);
448 SSL_CTX_free(server_ctx);
449 SSL_free(client_ssl);
450 SSL_free(server_ssl);
451
452 return failed;
453}
454
455int
456main(int argc, char **argv)
457{
458 size_t i;
459 int failed = 0;
460
461 if (asprintf(&server_cert, "%s/server1-rsa.pem", CERTSDIR) == -1) {
462 fprintf(stderr, "asprintf server_cert failed\n");
463 failed = 1;
464 goto err;
465 }
466 server_key = server_cert;
467
468 for (i = 0; i < N_SHARED_CIPHERS_TESTS; i++)
469 failed |= test_get_shared_ciphers(&ssl_shared_ciphers_tests[i]);
470
471 if (failed == 0)
472 printf("PASS %s\n", __FILE__);
473
474 err:
475 free(server_cert);
476
477 return failed;
478}