summaryrefslogtreecommitdiff
path: root/src/regress/lib/libssl/unit/ssl_set_alpn_protos.c
diff options
context:
space:
mode:
authorcvs2svn <admin@example.com>2025-04-14 17:32:06 +0000
committercvs2svn <admin@example.com>2025-04-14 17:32:06 +0000
commiteb8dd9dca1228af0cd132f515509051ecfabf6f6 (patch)
treeedb6da6af7e865d488dc1a29309f1e1ec226e603 /src/regress/lib/libssl/unit/ssl_set_alpn_protos.c
parent247f0352e0ed72a4f476db9dc91f4d982bc83eb2 (diff)
downloadopenbsd-tb_20250414.tar.gz
openbsd-tb_20250414.tar.bz2
openbsd-tb_20250414.zip
This commit was manufactured by cvs2git to create tag 'tb_20250414'.tb_20250414
Diffstat (limited to 'src/regress/lib/libssl/unit/ssl_set_alpn_protos.c')
-rw-r--r--src/regress/lib/libssl/unit/ssl_set_alpn_protos.c470
1 files changed, 0 insertions, 470 deletions
diff --git a/src/regress/lib/libssl/unit/ssl_set_alpn_protos.c b/src/regress/lib/libssl/unit/ssl_set_alpn_protos.c
deleted file mode 100644
index d8447c8999..0000000000
--- a/src/regress/lib/libssl/unit/ssl_set_alpn_protos.c
+++ /dev/null
@@ -1,470 +0,0 @@
1/* $OpenBSD: ssl_set_alpn_protos.c,v 1.4 2024/07/11 13:51:47 tb Exp $ */
2/*
3 * Copyright (c) 2022 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 <err.h>
19#include <stdio.h>
20
21#include <openssl/ssl.h>
22
23static void
24hexdump(const unsigned char *buf, size_t len)
25{
26 size_t i;
27
28 if (buf == NULL) {
29 fprintf(stderr, "(null), len %zu\n", len);
30 return;
31 }
32 for (i = 1; i <= len; i++)
33 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
34 if (len % 8)
35 fprintf(stderr, "\n");
36}
37
38struct alpn_test {
39 const char *description;
40 const uint8_t protocols[24];
41 size_t protocols_len;
42 int ret;
43};
44
45static const struct alpn_test alpn_tests[] = {
46 {
47 .description = "valid protocol list",
48 .protocols = {
49 6, 's', 'p', 'd', 'y', '/', '1',
50 8, 'h', 't', 't', 'p', '/', '1', '.', '1',
51 },
52 .protocols_len = 16,
53 .ret = 0,
54 },
55 {
56 .description = "zero length protocol",
57 .protocols = {
58 0,
59 },
60 .protocols_len = 1,
61 .ret = 1,
62 },
63 {
64 .description = "zero length protocol at start",
65 .protocols = {
66 0,
67 8, 'h', 't', 't', 'p', '/', '1', '.', '1',
68 6, 's', 'p', 'd', 'y', '/', '1',
69 },
70 .protocols_len = 17,
71 .ret = 1,
72 },
73 {
74 .description = "zero length protocol embedded",
75 .protocols = {
76 8, 'h', 't', 't', 'p', '/', '1', '.', '1',
77 0,
78 6, 's', 'p', 'd', 'y', '/', '1',
79 },
80 .protocols_len = 17,
81 .ret = 1,
82 },
83 {
84 .description = "zero length protocol at end",
85 .protocols = {
86 8, 'h', 't', 't', 'p', '/', '1', '.', '1',
87 6, 's', 'p', 'd', 'y', '/', '1',
88 0,
89 },
90 .protocols_len = 17,
91 .ret = 1,
92 },
93 {
94 .description = "protocol length too short",
95 .protocols = {
96 6, 'h', 't', 't', 'p', '/', '1', '.', '1',
97 },
98 .protocols_len = 9,
99 .ret = 1,
100 },
101 {
102 .description = "protocol length too long",
103 .protocols = {
104 8, 's', 'p', 'd', 'y', '/', '1',
105 },
106 .protocols_len = 7,
107 .ret = 1,
108 },
109};
110
111static const size_t N_ALPN_TESTS = sizeof(alpn_tests) / sizeof(alpn_tests[0]);
112
113static int
114test_ssl_set_alpn_protos(const struct alpn_test *tc)
115{
116 SSL_CTX *ctx;
117 SSL *ssl;
118 int ret;
119 int failed = 0;
120
121 if ((ctx = SSL_CTX_new(TLS_client_method())) == NULL)
122 errx(1, "SSL_CTX_new");
123
124 ret = SSL_CTX_set_alpn_protos(ctx, tc->protocols, tc->protocols_len);
125 if (ret != tc->ret) {
126 warnx("%s: setting on SSL_CTX: want %d, got %d",
127 tc->description, tc->ret, ret);
128 failed = 1;
129 }
130
131 if ((ssl = SSL_new(ctx)) == NULL)
132 errx(1, "SSL_new");
133
134 ret = SSL_set_alpn_protos(ssl, tc->protocols, tc->protocols_len);
135 if (ret != tc->ret) {
136 warnx("%s: setting on SSL: want %d, got %d",
137 tc->description, tc->ret, ret);
138 failed = 1;
139 }
140
141 SSL_CTX_free(ctx);
142 SSL_free(ssl);
143
144 return failed;
145}
146
147static int
148test_ssl_set_alpn_protos_edge_cases(void)
149{
150 SSL_CTX *ctx;
151 SSL *ssl;
152 const uint8_t valid[] = {
153 6, 's', 'p', 'd', 'y', '/', '3',
154 8, 'h', 't', 't', 'p', '/', '1', '.', '1',
155 };
156 int failed = 0;
157
158 if ((ctx = SSL_CTX_new(TLS_client_method())) == NULL)
159 errx(1, "SSL_CTX_new");
160
161 if (SSL_CTX_set_alpn_protos(ctx, valid, sizeof(valid)) != 0) {
162 warnx("setting valid protocols on SSL_CTX failed");
163 failed = 1;
164 }
165 if (SSL_CTX_set_alpn_protos(ctx, NULL, 0) != 0) {
166 warnx("setting 'NULL, 0' on SSL_CTX failed");
167 failed = 1;
168 }
169 if (SSL_CTX_set_alpn_protos(ctx, valid, 0) != 0) {
170 warnx("setting 'valid, 0' on SSL_CTX failed");
171 failed = 1;
172 }
173 if (SSL_CTX_set_alpn_protos(ctx, NULL, 43) != 0) {
174 warnx("setting 'NULL, 43' on SSL_CTX failed");
175 failed = 1;
176 }
177
178 if ((ssl = SSL_new(ctx)) == NULL)
179 errx(1, "SSL_new");
180
181 if (SSL_set_alpn_protos(ssl, valid, sizeof(valid)) != 0) {
182 warnx("setting valid protocols on SSL failed");
183 failed = 1;
184 }
185 if (SSL_set_alpn_protos(ssl, NULL, 0) != 0) {
186 warnx("setting 'NULL, 0' on SSL failed");
187 failed = 1;
188 }
189 if (SSL_set_alpn_protos(ssl, valid, 0) != 0) {
190 warnx("setting 'valid, 0' on SSL failed");
191 failed = 1;
192 }
193 if (SSL_set_alpn_protos(ssl, NULL, 43) != 0) {
194 warnx("setting 'NULL, 43' on SSL failed");
195 failed = 1;
196 }
197
198 SSL_CTX_free(ctx);
199 SSL_free(ssl);
200
201 return failed;
202}
203
204static const struct select_next_proto_test {
205 const unsigned char *peer_list;
206 size_t peer_list_len;
207 const unsigned char *supported_list;
208 size_t supported_list_len;
209 int want_ret;
210 const unsigned char *want_out;
211 unsigned char want_out_len; /* yes, unsigned char */
212} select_next_proto_tests[] = {
213 {
214 .peer_list = "\x01" "a" "\x01" "b" "\x01" "c",
215 .peer_list_len = 6,
216 .supported_list = "\x01" "a",
217 .supported_list_len = 2,
218 .want_ret = OPENSSL_NPN_NEGOTIATED,
219 .want_out = "a",
220 .want_out_len = 1,
221 },
222 {
223 .peer_list = "\x01" "a" "\x01" "b" "\x01" "c",
224 .peer_list_len = 6,
225 .supported_list = "\x02" "aa" "\x01" "b" "\x01" "c",
226 .supported_list_len = 7,
227 .want_ret = OPENSSL_NPN_NEGOTIATED,
228 .want_out = "b",
229 .want_out_len = 1,
230 },
231 {
232 /* Use peer preference. */
233 .peer_list = "\x01" "a" "\x01" "b" "\x01" "c",
234 .peer_list_len = 6,
235 .supported_list = "\x01" "c" "\x01" "b" "\x01" "a",
236 .supported_list_len = 6,
237 .want_ret = OPENSSL_NPN_NEGOTIATED,
238 .want_out = "a",
239 .want_out_len = 1,
240 },
241 {
242 /* Again peer preference wins. */
243 .peer_list = "\x01" "a" "\x03" "bbb" "\x02" "cc",
244 .peer_list_len = 9,
245 .supported_list = "\x01" "z" "\x02" "cc" "\x03" "bbb",
246 .supported_list_len = 9,
247 .want_ret = OPENSSL_NPN_NEGOTIATED,
248 .want_out = "bbb",
249 .want_out_len = 3,
250 },
251 {
252 /* No overlap fails with first supported protocol. */
253 .peer_list = "\x01" "a" "\x01" "b" "\x01" "c",
254 .peer_list_len = 6,
255 .supported_list = "\x01" "z" "\x01" "y",
256 .supported_list_len = 4,
257 .want_ret = OPENSSL_NPN_NO_OVERLAP,
258 .want_out = "z",
259 .want_out_len = 1,
260 },
261 {
262 /* No peer protocols fails cleanly. */
263 .peer_list = "",
264 .peer_list_len = 0,
265 .supported_list = "\x01" "a" "\x01" "b" "\x01" "c",
266 .supported_list_len = 6,
267 .want_out = "a",
268 .want_out_len = 1,
269 .want_ret = OPENSSL_NPN_NO_OVERLAP,
270 },
271 {
272 /* NULL peer protocols fails cleanly. */
273 .peer_list = NULL,
274 .peer_list_len = 0,
275 .supported_list = "\x01" "a" "\x01" "b" "\x01" "c",
276 .supported_list_len = 6,
277 .want_out = "a",
278 .want_out_len = 1,
279 .want_ret = OPENSSL_NPN_NO_OVERLAP,
280 },
281 {
282 /* Malformed peer protocols fails cleanly. */
283 .peer_list = "\x00",
284 .peer_list_len = 1,
285 .supported_list = "\x01" "a" "\x01" "b" "\x01" "c",
286 .supported_list_len = 6,
287 .want_out = "a",
288 .want_out_len = 1,
289 .want_ret = OPENSSL_NPN_NO_OVERLAP,
290 },
291 {
292 /* Malformed peer protocols fails cleanly. */
293 .peer_list = "\x01" "a" "\x03" "bb",
294 .peer_list_len = 5,
295 .supported_list = "\x01" "a" "\x01" "b" "\x01" "c",
296 .supported_list_len = 6,
297 .want_out = "a",
298 .want_out_len = 1,
299 .want_ret = OPENSSL_NPN_NO_OVERLAP,
300 },
301 {
302 /* Empty supported list fails cleanly. */
303 .peer_list = "\x01" "a",
304 .peer_list_len = 2,
305 .supported_list = "",
306 .supported_list_len = 0,
307 .want_out = NULL,
308 .want_out_len = 0,
309 .want_ret = OPENSSL_NPN_NO_OVERLAP,
310 },
311 {
312 /* NULL supported list fails cleanly. */
313 .peer_list = "\x01" "a",
314 .peer_list_len = 2,
315 .supported_list = NULL,
316 .supported_list_len = 0,
317 .want_out = NULL,
318 .want_out_len = 0,
319 .want_ret = OPENSSL_NPN_NO_OVERLAP,
320 },
321 {
322 /* Malformed supported list fails cleanly. */
323 .peer_list = "\x01" "a",
324 .peer_list_len = 2,
325 .supported_list = "\x01" "a" "\x02" "bb" "\x03" "cc" "\x04" "ddd",
326 .supported_list_len = 12,
327 .want_out = NULL,
328 .want_out_len = 0,
329 .want_ret = OPENSSL_NPN_NO_OVERLAP,
330 },
331 {
332 /* Malformed client list fails cleanly. */
333 .peer_list = "\x01" "a",
334 .peer_list_len = 2,
335 .supported_list = "\x01" "a" "\x02" "bb" "\x00" "\x03" "ddd",
336 .supported_list_len = 10,
337 .want_out = NULL,
338 .want_out_len = 0,
339 .want_ret = OPENSSL_NPN_NO_OVERLAP,
340 },
341
342 /*
343 * Some non-toy examples.
344 */
345
346 {
347 .peer_list = "\x08" "http/1.1" "\x06" "spdy/1",
348 .peer_list_len = 16,
349 .supported_list = "\x08" "http/2.0" "\x08" "http/1.1",
350 .supported_list_len = 18,
351 .want_out = "http/1.1",
352 .want_out_len = 8,
353 .want_ret = OPENSSL_NPN_NEGOTIATED,
354 },
355 {
356 .peer_list = "\x08" "http/2.0" "\x06" "spdy/1",
357 .peer_list_len = 16,
358 .supported_list = "\x08" "http/1.0" "\x08" "http/1.1",
359 .supported_list_len = 18,
360 .want_out = "http/1.0",
361 .want_out_len = 8,
362 .want_ret = OPENSSL_NPN_NO_OVERLAP,
363 },
364 {
365 .peer_list = "\x08" "http/1.1" "\x08" "http/1.0",
366 .peer_list_len = 18,
367 .supported_list = "\x08" "http/1.0" "\x08" "http/1.1",
368 .supported_list_len = 18,
369 .want_out = "http/1.1",
370 .want_out_len = 8,
371 .want_ret = OPENSSL_NPN_NEGOTIATED,
372 },
373 {
374 /* Peer list malformed. */
375 .peer_list = "\x08" "http/1.1" "\x07" "http/1.0",
376 .peer_list_len = 18,
377 .supported_list = "\x08" "http/1.0" "\x08" "http/1.1",
378 .supported_list_len = 18,
379 .want_out = "http/1.0",
380 .want_out_len = 8,
381 .want_ret = OPENSSL_NPN_NO_OVERLAP,
382 },
383 {
384 /* Peer list malformed. */
385 .peer_list = "\x07" "http/1.1" "\x08" "http/1.0",
386 .peer_list_len = 18,
387 .supported_list = "\x08" "http/1.0" "\x08" "http/1.1",
388 .supported_list_len = 18,
389 .want_out = "http/1.0",
390 .want_out_len = 8,
391 .want_ret = OPENSSL_NPN_NO_OVERLAP,
392 },
393 {
394 /* Supported list has trailing bytes. */
395 .peer_list = "\x08" "http/1.1" "\x08" "http/1.0",
396 .peer_list_len = 18,
397 .supported_list = "\x08" "http/1.0" "\x07" "http/1.1",
398 .supported_list_len = 18,
399 .want_out = NULL,
400 .want_out_len = 0,
401 .want_ret = OPENSSL_NPN_NO_OVERLAP,
402 },
403};
404
405#define N_SELECT_NEXT_PROTO_TESTS \
406 (sizeof(select_next_proto_tests) / sizeof(select_next_proto_tests[0]))
407
408static int
409select_next_proto_testcase(const struct select_next_proto_test *test)
410{
411 unsigned char *out;
412 unsigned char out_len;
413 int ret;
414 int failed = 0;
415
416 ret = SSL_select_next_proto(&out, &out_len, test->peer_list,
417 test->peer_list_len, test->supported_list, test->supported_list_len);
418
419 if (ret != test->want_ret || out_len != test->want_out_len ||
420 (out == NULL && test->want_out != NULL) ||
421 (out != NULL && test->want_out == NULL) ||
422 (out != NULL && test->want_out != NULL &&
423 memcmp(out, test->want_out, out_len) != 0)) {
424 fprintf(stderr, "FAIL: ret: %u (want %u), out_len: %u (want %u)\n",
425 ret, test->want_ret, out_len, test->want_out_len);
426 fprintf(stderr, "\ngot:\n");
427 hexdump(out, out_len);
428 fprintf(stderr, "\nwant:\n");
429 hexdump(test->want_out, test->want_out_len);
430 fprintf(stderr, "\nserver:\n");
431 hexdump(test->peer_list, test->peer_list_len);
432 fprintf(stderr, "\nclient:\n");
433 hexdump(test->supported_list, test->supported_list_len);
434 fprintf(stderr, "\n");
435 failed = 1;
436 }
437
438 return failed;
439}
440
441static int
442test_ssl_select_next_proto(void)
443{
444 size_t i;
445 int failed = 0;
446
447 for (i = 0; i < N_SELECT_NEXT_PROTO_TESTS; i++)
448 failed |= select_next_proto_testcase(&select_next_proto_tests[i]);
449
450 return failed;
451}
452
453int
454main(void)
455{
456 size_t i;
457 int failed = 0;
458
459 for (i = 0; i < N_ALPN_TESTS; i++)
460 failed |= test_ssl_set_alpn_protos(&alpn_tests[i]);
461
462 failed |= test_ssl_set_alpn_protos_edge_cases();
463
464 failed |= test_ssl_select_next_proto();
465
466 if (!failed)
467 printf("PASS %s\n", __FILE__);
468
469 return failed;
470}