diff options
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.c | 470 |
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 | |||
23 | static void | ||
24 | hexdump(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 | |||
38 | struct alpn_test { | ||
39 | const char *description; | ||
40 | const uint8_t protocols[24]; | ||
41 | size_t protocols_len; | ||
42 | int ret; | ||
43 | }; | ||
44 | |||
45 | static 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 | |||
111 | static const size_t N_ALPN_TESTS = sizeof(alpn_tests) / sizeof(alpn_tests[0]); | ||
112 | |||
113 | static int | ||
114 | test_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 | |||
147 | static int | ||
148 | test_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 | |||
204 | static 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 | |||
408 | static int | ||
409 | select_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 | |||
441 | static int | ||
442 | test_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 | |||
453 | int | ||
454 | main(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 | } | ||