1*668a98a4Stb /* $OpenBSD: ssl_set_alpn_protos.c,v 1.4 2024/07/11 13:51:47 tb Exp $ */
2fcc59a4aStb /*
3fcc59a4aStb * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
4fcc59a4aStb *
5fcc59a4aStb * Permission to use, copy, modify, and distribute this software for any
6fcc59a4aStb * purpose with or without fee is hereby granted, provided that the above
7fcc59a4aStb * copyright notice and this permission notice appear in all copies.
8fcc59a4aStb *
9fcc59a4aStb * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10fcc59a4aStb * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11fcc59a4aStb * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12fcc59a4aStb * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13fcc59a4aStb * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14fcc59a4aStb * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15fcc59a4aStb * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16fcc59a4aStb */
17fcc59a4aStb
18fcc59a4aStb #include <err.h>
19fcc59a4aStb #include <stdio.h>
20fcc59a4aStb
21fcc59a4aStb #include <openssl/ssl.h>
22fcc59a4aStb
234e890224Stb static void
hexdump(const unsigned char * buf,size_t len)244e890224Stb hexdump(const unsigned char *buf, size_t len)
254e890224Stb {
264e890224Stb size_t i;
274e890224Stb
284e890224Stb if (buf == NULL) {
294e890224Stb fprintf(stderr, "(null), len %zu\n", len);
304e890224Stb return;
314e890224Stb }
324e890224Stb for (i = 1; i <= len; i++)
334e890224Stb fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
344e890224Stb if (len % 8)
354e890224Stb fprintf(stderr, "\n");
364e890224Stb }
374e890224Stb
388b3eb788Stb struct alpn_test {
398b3eb788Stb const char *description;
408b3eb788Stb const uint8_t protocols[24];
418b3eb788Stb size_t protocols_len;
428b3eb788Stb int ret;
438b3eb788Stb };
448b3eb788Stb
458b3eb788Stb static const struct alpn_test alpn_tests[] = {
468b3eb788Stb {
478b3eb788Stb .description = "valid protocol list",
488b3eb788Stb .protocols = {
49fcc59a4aStb 6, 's', 'p', 'd', 'y', '/', '1',
50fcc59a4aStb 8, 'h', 't', 't', 'p', '/', '1', '.', '1',
518b3eb788Stb },
528b3eb788Stb .protocols_len = 16,
538b3eb788Stb .ret = 0,
548b3eb788Stb },
558b3eb788Stb {
568b3eb788Stb .description = "zero length protocol",
578b3eb788Stb .protocols = {
58fcc59a4aStb 0,
598b3eb788Stb },
608b3eb788Stb .protocols_len = 1,
618b3eb788Stb .ret = 1,
628b3eb788Stb },
638b3eb788Stb {
648b3eb788Stb .description = "zero length protocol at start",
658b3eb788Stb .protocols = {
668b3eb788Stb 0,
678b3eb788Stb 8, 'h', 't', 't', 'p', '/', '1', '.', '1',
688b3eb788Stb 6, 's', 'p', 'd', 'y', '/', '1',
698b3eb788Stb },
708b3eb788Stb .protocols_len = 17,
718b3eb788Stb .ret = 1,
728b3eb788Stb },
738b3eb788Stb {
748b3eb788Stb .description = "zero length protocol embedded",
758b3eb788Stb .protocols = {
76fcc59a4aStb 8, 'h', 't', 't', 'p', '/', '1', '.', '1',
77fcc59a4aStb 0,
78fcc59a4aStb 6, 's', 'p', 'd', 'y', '/', '1',
798b3eb788Stb },
808b3eb788Stb .protocols_len = 17,
818b3eb788Stb .ret = 1,
828b3eb788Stb },
838b3eb788Stb {
848b3eb788Stb .description = "zero length protocol at end",
858b3eb788Stb .protocols = {
868b3eb788Stb 8, 'h', 't', 't', 'p', '/', '1', '.', '1',
878b3eb788Stb 6, 's', 'p', 'd', 'y', '/', '1',
888b3eb788Stb 0,
898b3eb788Stb },
908b3eb788Stb .protocols_len = 17,
918b3eb788Stb .ret = 1,
928b3eb788Stb },
938b3eb788Stb {
948b3eb788Stb .description = "protocol length too short",
958b3eb788Stb .protocols = {
96fcc59a4aStb 6, 'h', 't', 't', 'p', '/', '1', '.', '1',
978b3eb788Stb },
988b3eb788Stb .protocols_len = 9,
998b3eb788Stb .ret = 1,
1008b3eb788Stb },
1018b3eb788Stb {
1028b3eb788Stb .description = "protocol length too long",
1038b3eb788Stb .protocols = {
1048b3eb788Stb 8, 's', 'p', 'd', 'y', '/', '1',
1058b3eb788Stb },
1068b3eb788Stb .protocols_len = 7,
1078b3eb788Stb .ret = 1,
1088b3eb788Stb },
109fcc59a4aStb };
110fcc59a4aStb
1118b3eb788Stb static const size_t N_ALPN_TESTS = sizeof(alpn_tests) / sizeof(alpn_tests[0]);
112fcc59a4aStb
113fcc59a4aStb static int
test_ssl_set_alpn_protos(const struct alpn_test * tc)1148b3eb788Stb test_ssl_set_alpn_protos(const struct alpn_test *tc)
115fcc59a4aStb {
116fcc59a4aStb SSL_CTX *ctx;
1178b3eb788Stb SSL *ssl;
1188b3eb788Stb int ret;
1198b3eb788Stb int failed = 0;
1208b3eb788Stb
1218b3eb788Stb if ((ctx = SSL_CTX_new(TLS_client_method())) == NULL)
1228b3eb788Stb errx(1, "SSL_CTX_new");
1238b3eb788Stb
1248b3eb788Stb ret = SSL_CTX_set_alpn_protos(ctx, tc->protocols, tc->protocols_len);
1258b3eb788Stb if (ret != tc->ret) {
1268b3eb788Stb warnx("%s: setting on SSL_CTX: want %d, got %d",
1278b3eb788Stb tc->description, tc->ret, ret);
1288b3eb788Stb failed = 1;
1298b3eb788Stb }
1308b3eb788Stb
1318b3eb788Stb if ((ssl = SSL_new(ctx)) == NULL)
1328b3eb788Stb errx(1, "SSL_new");
1338b3eb788Stb
1348b3eb788Stb ret = SSL_set_alpn_protos(ssl, tc->protocols, tc->protocols_len);
1358b3eb788Stb if (ret != tc->ret) {
1368b3eb788Stb warnx("%s: setting on SSL: want %d, got %d",
1378b3eb788Stb tc->description, tc->ret, ret);
1388b3eb788Stb failed = 1;
1398b3eb788Stb }
1408b3eb788Stb
1418b3eb788Stb SSL_CTX_free(ctx);
1428b3eb788Stb SSL_free(ssl);
1438b3eb788Stb
1448b3eb788Stb return failed;
1458b3eb788Stb }
1468b3eb788Stb
1478b3eb788Stb static int
test_ssl_set_alpn_protos_edge_cases(void)1488b3eb788Stb test_ssl_set_alpn_protos_edge_cases(void)
1498b3eb788Stb {
1508b3eb788Stb SSL_CTX *ctx;
1518b3eb788Stb SSL *ssl;
1528b3eb788Stb const uint8_t valid[] = {
1538b3eb788Stb 6, 's', 'p', 'd', 'y', '/', '3',
1548b3eb788Stb 8, 'h', 't', 't', 'p', '/', '1', '.', '1',
1558b3eb788Stb };
156fcc59a4aStb int failed = 0;
157fcc59a4aStb
158fcc59a4aStb if ((ctx = SSL_CTX_new(TLS_client_method())) == NULL)
159fcc59a4aStb errx(1, "SSL_CTX_new");
160fcc59a4aStb
161fcc59a4aStb if (SSL_CTX_set_alpn_protos(ctx, valid, sizeof(valid)) != 0) {
162fcc59a4aStb warnx("setting valid protocols on SSL_CTX failed");
163fcc59a4aStb failed = 1;
164fcc59a4aStb }
165fcc59a4aStb if (SSL_CTX_set_alpn_protos(ctx, NULL, 0) != 0) {
166fcc59a4aStb warnx("setting 'NULL, 0' on SSL_CTX failed");
167fcc59a4aStb failed = 1;
168fcc59a4aStb }
169fcc59a4aStb if (SSL_CTX_set_alpn_protos(ctx, valid, 0) != 0) {
170fcc59a4aStb warnx("setting 'valid, 0' on SSL_CTX failed");
171fcc59a4aStb failed = 1;
172fcc59a4aStb }
173fcc59a4aStb if (SSL_CTX_set_alpn_protos(ctx, NULL, 43) != 0) {
1748b3eb788Stb warnx("setting 'NULL, 43' on SSL_CTX failed");
175fcc59a4aStb failed = 1;
176fcc59a4aStb }
177fcc59a4aStb
178fcc59a4aStb if ((ssl = SSL_new(ctx)) == NULL)
179fcc59a4aStb errx(1, "SSL_new");
180fcc59a4aStb
181fcc59a4aStb if (SSL_set_alpn_protos(ssl, valid, sizeof(valid)) != 0) {
182fcc59a4aStb warnx("setting valid protocols on SSL failed");
183fcc59a4aStb failed = 1;
184fcc59a4aStb }
185fcc59a4aStb if (SSL_set_alpn_protos(ssl, NULL, 0) != 0) {
186fcc59a4aStb warnx("setting 'NULL, 0' on SSL failed");
187fcc59a4aStb failed = 1;
188fcc59a4aStb }
189fcc59a4aStb if (SSL_set_alpn_protos(ssl, valid, 0) != 0) {
190fcc59a4aStb warnx("setting 'valid, 0' on SSL failed");
191fcc59a4aStb failed = 1;
192fcc59a4aStb }
193fcc59a4aStb if (SSL_set_alpn_protos(ssl, NULL, 43) != 0) {
1948b3eb788Stb warnx("setting 'NULL, 43' on SSL failed");
195fcc59a4aStb failed = 1;
196fcc59a4aStb }
197fcc59a4aStb
198fcc59a4aStb SSL_CTX_free(ctx);
199fcc59a4aStb SSL_free(ssl);
200fcc59a4aStb
201fcc59a4aStb return failed;
202fcc59a4aStb }
203fcc59a4aStb
2044e890224Stb static const struct select_next_proto_test {
205*668a98a4Stb const unsigned char *peer_list;
206*668a98a4Stb size_t peer_list_len;
207*668a98a4Stb const unsigned char *supported_list;
208*668a98a4Stb size_t supported_list_len;
2094e890224Stb int want_ret;
2104e890224Stb const unsigned char *want_out;
2114e890224Stb unsigned char want_out_len; /* yes, unsigned char */
2124e890224Stb } select_next_proto_tests[] = {
2134e890224Stb {
214*668a98a4Stb .peer_list = "\x01" "a" "\x01" "b" "\x01" "c",
215*668a98a4Stb .peer_list_len = 6,
216*668a98a4Stb .supported_list = "\x01" "a",
217*668a98a4Stb .supported_list_len = 2,
2184e890224Stb .want_ret = OPENSSL_NPN_NEGOTIATED,
2194e890224Stb .want_out = "a",
2204e890224Stb .want_out_len = 1,
2214e890224Stb },
2224e890224Stb {
223*668a98a4Stb .peer_list = "\x01" "a" "\x01" "b" "\x01" "c",
224*668a98a4Stb .peer_list_len = 6,
225*668a98a4Stb .supported_list = "\x02" "aa" "\x01" "b" "\x01" "c",
226*668a98a4Stb .supported_list_len = 7,
2274e890224Stb .want_ret = OPENSSL_NPN_NEGOTIATED,
2284e890224Stb .want_out = "b",
2294e890224Stb .want_out_len = 1,
2304e890224Stb },
2314e890224Stb {
232*668a98a4Stb /* Use peer preference. */
233*668a98a4Stb .peer_list = "\x01" "a" "\x01" "b" "\x01" "c",
234*668a98a4Stb .peer_list_len = 6,
235*668a98a4Stb .supported_list = "\x01" "c" "\x01" "b" "\x01" "a",
236*668a98a4Stb .supported_list_len = 6,
2374e890224Stb .want_ret = OPENSSL_NPN_NEGOTIATED,
2384e890224Stb .want_out = "a",
2394e890224Stb .want_out_len = 1,
2404e890224Stb },
2414e890224Stb {
242*668a98a4Stb /* Again peer preference wins. */
243*668a98a4Stb .peer_list = "\x01" "a" "\x03" "bbb" "\x02" "cc",
244*668a98a4Stb .peer_list_len = 9,
245*668a98a4Stb .supported_list = "\x01" "z" "\x02" "cc" "\x03" "bbb",
246*668a98a4Stb .supported_list_len = 9,
2474e890224Stb .want_ret = OPENSSL_NPN_NEGOTIATED,
2484e890224Stb .want_out = "bbb",
2494e890224Stb .want_out_len = 3,
2504e890224Stb },
2514e890224Stb {
252*668a98a4Stb /* No overlap fails with first supported protocol. */
253*668a98a4Stb .peer_list = "\x01" "a" "\x01" "b" "\x01" "c",
254*668a98a4Stb .peer_list_len = 6,
255*668a98a4Stb .supported_list = "\x01" "z" "\x01" "y",
256*668a98a4Stb .supported_list_len = 4,
2574e890224Stb .want_ret = OPENSSL_NPN_NO_OVERLAP,
2584e890224Stb .want_out = "z",
2594e890224Stb .want_out_len = 1,
2604e890224Stb },
2614e890224Stb {
262*668a98a4Stb /* No peer protocols fails cleanly. */
263*668a98a4Stb .peer_list = "",
264*668a98a4Stb .peer_list_len = 0,
265*668a98a4Stb .supported_list = "\x01" "a" "\x01" "b" "\x01" "c",
266*668a98a4Stb .supported_list_len = 6,
2674e890224Stb .want_out = "a",
2684e890224Stb .want_out_len = 1,
2694e890224Stb .want_ret = OPENSSL_NPN_NO_OVERLAP,
2704e890224Stb },
2714e890224Stb {
272*668a98a4Stb /* NULL peer protocols fails cleanly. */
273*668a98a4Stb .peer_list = NULL,
274*668a98a4Stb .peer_list_len = 0,
275*668a98a4Stb .supported_list = "\x01" "a" "\x01" "b" "\x01" "c",
276*668a98a4Stb .supported_list_len = 6,
2774e890224Stb .want_out = "a",
2784e890224Stb .want_out_len = 1,
2794e890224Stb .want_ret = OPENSSL_NPN_NO_OVERLAP,
2804e890224Stb },
2814e890224Stb {
282*668a98a4Stb /* Malformed peer protocols fails cleanly. */
283*668a98a4Stb .peer_list = "\x00",
284*668a98a4Stb .peer_list_len = 1,
285*668a98a4Stb .supported_list = "\x01" "a" "\x01" "b" "\x01" "c",
286*668a98a4Stb .supported_list_len = 6,
2874e890224Stb .want_out = "a",
2884e890224Stb .want_out_len = 1,
2894e890224Stb .want_ret = OPENSSL_NPN_NO_OVERLAP,
2904e890224Stb },
2914e890224Stb {
292*668a98a4Stb /* Malformed peer protocols fails cleanly. */
293*668a98a4Stb .peer_list = "\x01" "a" "\x03" "bb",
294*668a98a4Stb .peer_list_len = 5,
295*668a98a4Stb .supported_list = "\x01" "a" "\x01" "b" "\x01" "c",
296*668a98a4Stb .supported_list_len = 6,
2974e890224Stb .want_out = "a",
2984e890224Stb .want_out_len = 1,
2994e890224Stb .want_ret = OPENSSL_NPN_NO_OVERLAP,
3004e890224Stb },
3014e890224Stb {
302*668a98a4Stb /* Empty supported list fails cleanly. */
303*668a98a4Stb .peer_list = "\x01" "a",
304*668a98a4Stb .peer_list_len = 2,
305*668a98a4Stb .supported_list = "",
306*668a98a4Stb .supported_list_len = 0,
3074e890224Stb .want_out = NULL,
3084e890224Stb .want_out_len = 0,
3094e890224Stb .want_ret = OPENSSL_NPN_NO_OVERLAP,
3104e890224Stb },
3114e890224Stb {
312*668a98a4Stb /* NULL supported list fails cleanly. */
313*668a98a4Stb .peer_list = "\x01" "a",
314*668a98a4Stb .peer_list_len = 2,
315*668a98a4Stb .supported_list = NULL,
316*668a98a4Stb .supported_list_len = 0,
3174e890224Stb .want_out = NULL,
3184e890224Stb .want_out_len = 0,
3194e890224Stb .want_ret = OPENSSL_NPN_NO_OVERLAP,
3204e890224Stb },
3214e890224Stb {
322*668a98a4Stb /* Malformed supported list fails cleanly. */
323*668a98a4Stb .peer_list = "\x01" "a",
324*668a98a4Stb .peer_list_len = 2,
325*668a98a4Stb .supported_list = "\x01" "a" "\x02" "bb" "\x03" "cc" "\x04" "ddd",
326*668a98a4Stb .supported_list_len = 12,
3274e890224Stb .want_out = NULL,
3284e890224Stb .want_out_len = 0,
3294e890224Stb .want_ret = OPENSSL_NPN_NO_OVERLAP,
3304e890224Stb },
3314e890224Stb {
332*668a98a4Stb /* Malformed client list fails cleanly. */
333*668a98a4Stb .peer_list = "\x01" "a",
334*668a98a4Stb .peer_list_len = 2,
335*668a98a4Stb .supported_list = "\x01" "a" "\x02" "bb" "\x00" "\x03" "ddd",
336*668a98a4Stb .supported_list_len = 10,
3374e890224Stb .want_out = NULL,
3384e890224Stb .want_out_len = 0,
3394e890224Stb .want_ret = OPENSSL_NPN_NO_OVERLAP,
3404e890224Stb },
3414e890224Stb
3424e890224Stb /*
3434e890224Stb * Some non-toy examples.
3444e890224Stb */
3454e890224Stb
3464e890224Stb {
347*668a98a4Stb .peer_list = "\x08" "http/1.1" "\x06" "spdy/1",
348*668a98a4Stb .peer_list_len = 16,
349*668a98a4Stb .supported_list = "\x08" "http/2.0" "\x08" "http/1.1",
350*668a98a4Stb .supported_list_len = 18,
3514e890224Stb .want_out = "http/1.1",
3524e890224Stb .want_out_len = 8,
3534e890224Stb .want_ret = OPENSSL_NPN_NEGOTIATED,
3544e890224Stb },
3554e890224Stb {
356*668a98a4Stb .peer_list = "\x08" "http/2.0" "\x06" "spdy/1",
357*668a98a4Stb .peer_list_len = 16,
358*668a98a4Stb .supported_list = "\x08" "http/1.0" "\x08" "http/1.1",
359*668a98a4Stb .supported_list_len = 18,
3604e890224Stb .want_out = "http/1.0",
3614e890224Stb .want_out_len = 8,
3624e890224Stb .want_ret = OPENSSL_NPN_NO_OVERLAP,
3634e890224Stb },
3644e890224Stb {
365*668a98a4Stb .peer_list = "\x08" "http/1.1" "\x08" "http/1.0",
366*668a98a4Stb .peer_list_len = 18,
367*668a98a4Stb .supported_list = "\x08" "http/1.0" "\x08" "http/1.1",
368*668a98a4Stb .supported_list_len = 18,
3694e890224Stb .want_out = "http/1.1",
3704e890224Stb .want_out_len = 8,
3714e890224Stb .want_ret = OPENSSL_NPN_NEGOTIATED,
3724e890224Stb },
3734e890224Stb {
374*668a98a4Stb /* Peer list malformed. */
375*668a98a4Stb .peer_list = "\x08" "http/1.1" "\x07" "http/1.0",
376*668a98a4Stb .peer_list_len = 18,
377*668a98a4Stb .supported_list = "\x08" "http/1.0" "\x08" "http/1.1",
378*668a98a4Stb .supported_list_len = 18,
3794e890224Stb .want_out = "http/1.0",
3804e890224Stb .want_out_len = 8,
3814e890224Stb .want_ret = OPENSSL_NPN_NO_OVERLAP,
3824e890224Stb },
3834e890224Stb {
384*668a98a4Stb /* Peer list malformed. */
385*668a98a4Stb .peer_list = "\x07" "http/1.1" "\x08" "http/1.0",
386*668a98a4Stb .peer_list_len = 18,
387*668a98a4Stb .supported_list = "\x08" "http/1.0" "\x08" "http/1.1",
388*668a98a4Stb .supported_list_len = 18,
3894e890224Stb .want_out = "http/1.0",
3904e890224Stb .want_out_len = 8,
3914e890224Stb .want_ret = OPENSSL_NPN_NO_OVERLAP,
3924e890224Stb },
3934e890224Stb {
394*668a98a4Stb /* Supported list has trailing bytes. */
395*668a98a4Stb .peer_list = "\x08" "http/1.1" "\x08" "http/1.0",
396*668a98a4Stb .peer_list_len = 18,
397*668a98a4Stb .supported_list = "\x08" "http/1.0" "\x07" "http/1.1",
398*668a98a4Stb .supported_list_len = 18,
3994e890224Stb .want_out = NULL,
4004e890224Stb .want_out_len = 0,
4014e890224Stb .want_ret = OPENSSL_NPN_NO_OVERLAP,
4024e890224Stb },
4034e890224Stb };
4044e890224Stb
4054e890224Stb #define N_SELECT_NEXT_PROTO_TESTS \
4064e890224Stb (sizeof(select_next_proto_tests) / sizeof(select_next_proto_tests[0]))
4074e890224Stb
4084e890224Stb static int
select_next_proto_testcase(const struct select_next_proto_test * test)4094e890224Stb select_next_proto_testcase(const struct select_next_proto_test *test)
4104e890224Stb {
4114e890224Stb unsigned char *out;
4124e890224Stb unsigned char out_len;
4134e890224Stb int ret;
4144e890224Stb int failed = 0;
4154e890224Stb
416*668a98a4Stb ret = SSL_select_next_proto(&out, &out_len, test->peer_list,
417*668a98a4Stb test->peer_list_len, test->supported_list, test->supported_list_len);
4184e890224Stb
4194e890224Stb if (ret != test->want_ret || out_len != test->want_out_len ||
4204e890224Stb (out == NULL && test->want_out != NULL) ||
4214e890224Stb (out != NULL && test->want_out == NULL) ||
4224e890224Stb (out != NULL && test->want_out != NULL &&
4234e890224Stb memcmp(out, test->want_out, out_len) != 0)) {
4244e890224Stb fprintf(stderr, "FAIL: ret: %u (want %u), out_len: %u (want %u)\n",
4254e890224Stb ret, test->want_ret, out_len, test->want_out_len);
4264e890224Stb fprintf(stderr, "\ngot:\n");
4274e890224Stb hexdump(out, out_len);
4284e890224Stb fprintf(stderr, "\nwant:\n");
4294e890224Stb hexdump(test->want_out, test->want_out_len);
4304e890224Stb fprintf(stderr, "\nserver:\n");
431*668a98a4Stb hexdump(test->peer_list, test->peer_list_len);
4324e890224Stb fprintf(stderr, "\nclient:\n");
433*668a98a4Stb hexdump(test->supported_list, test->supported_list_len);
4344e890224Stb fprintf(stderr, "\n");
4354e890224Stb failed = 1;
4364e890224Stb }
4374e890224Stb
4384e890224Stb return failed;
4394e890224Stb }
4404e890224Stb
4414e890224Stb static int
test_ssl_select_next_proto(void)4424e890224Stb test_ssl_select_next_proto(void)
4434e890224Stb {
4444e890224Stb size_t i;
4454e890224Stb int failed = 0;
4464e890224Stb
4474e890224Stb for (i = 0; i < N_SELECT_NEXT_PROTO_TESTS; i++)
4484e890224Stb failed |= select_next_proto_testcase(&select_next_proto_tests[i]);
4494e890224Stb
4504e890224Stb return failed;
4514e890224Stb }
4524e890224Stb
453fcc59a4aStb int
main(void)454fcc59a4aStb main(void)
455fcc59a4aStb {
4568b3eb788Stb size_t i;
4578b3eb788Stb int failed = 0;
458fcc59a4aStb
4598b3eb788Stb for (i = 0; i < N_ALPN_TESTS; i++)
4608b3eb788Stb failed |= test_ssl_set_alpn_protos(&alpn_tests[i]);
4618b3eb788Stb
4628b3eb788Stb failed |= test_ssl_set_alpn_protos_edge_cases();
463fcc59a4aStb
4644e890224Stb failed |= test_ssl_select_next_proto();
4654e890224Stb
466fcc59a4aStb if (!failed)
467fcc59a4aStb printf("PASS %s\n", __FILE__);
468fcc59a4aStb
469fcc59a4aStb return failed;
470fcc59a4aStb }
471