summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordoug <>2017-08-26 20:23:46 +0000
committerdoug <>2017-08-26 20:23:46 +0000
commit4d875aa977b8bbe9969527101d0f2d7d67a77b0b (patch)
treed42347fee889bfbea6b518ea0c0bc8a2f6c60bc0
parent8d42eef4813a62fe0da8095168237e06c798bcd1 (diff)
downloadopenbsd-4d875aa977b8bbe9969527101d0f2d7d67a77b0b.tar.gz
openbsd-4d875aa977b8bbe9969527101d0f2d7d67a77b0b.tar.bz2
openbsd-4d875aa977b8bbe9969527101d0f2d7d67a77b0b.zip
Rewrite ALPN extension using CBB/CBS and the new extension framework.
ok bcook@ beck@ input + ok jsing@
-rw-r--r--src/lib/libssl/ssl_locl.h4
-rw-r--r--src/lib/libssl/ssl_tlsext.c149
-rw-r--r--src/lib/libssl/ssl_tlsext.h9
-rw-r--r--src/lib/libssl/t1_lib.c140
-rw-r--r--src/regress/lib/libssl/tlsext/tlsexttest.c382
5 files changed, 540 insertions, 144 deletions
diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h
index ddb3b30327..624df9c929 100644
--- a/src/lib/libssl/ssl_locl.h
+++ b/src/lib/libssl/ssl_locl.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssl_locl.h,v 1.190 2017/08/12 21:47:59 jsing Exp $ */ 1/* $OpenBSD: ssl_locl.h,v 1.191 2017/08/26 20:23:46 doug Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -864,7 +864,7 @@ typedef struct ssl3_state_internal_st {
864 * processed. 864 * processed.
865 */ 865 */
866 unsigned char *alpn_selected; 866 unsigned char *alpn_selected;
867 unsigned int alpn_selected_len; 867 size_t alpn_selected_len;
868} SSL3_STATE_INTERNAL; 868} SSL3_STATE_INTERNAL;
869#define S3I(s) (s->s3->internal) 869#define S3I(s) (s->s3->internal)
870 870
diff --git a/src/lib/libssl/ssl_tlsext.c b/src/lib/libssl/ssl_tlsext.c
index 60daff6f8d..405882c0e9 100644
--- a/src/lib/libssl/ssl_tlsext.c
+++ b/src/lib/libssl/ssl_tlsext.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssl_tlsext.c,v 1.10 2017/08/23 15:39:38 doug Exp $ */ 1/* $OpenBSD: ssl_tlsext.c,v 1.11 2017/08/26 20:23:46 doug Exp $ */
2/* 2/*
3 * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> 4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
@@ -23,6 +23,144 @@
23#include "bytestring.h" 23#include "bytestring.h"
24#include "ssl_tlsext.h" 24#include "ssl_tlsext.h"
25 25
26/*
27 * Supported Application-Layer Protocol Negotiation - RFC 7301
28 */
29
30int
31tlsext_alpn_clienthello_needs(SSL *s)
32{
33 /* ALPN protos have been specified and this is the initial handshake */
34 return s->internal->alpn_client_proto_list != NULL &&
35 S3I(s)->tmp.finish_md_len == 0;
36}
37
38int
39tlsext_alpn_clienthello_build(SSL *s, CBB *cbb)
40{
41 CBB protolist;
42
43 if (!CBB_add_u16_length_prefixed(cbb, &protolist))
44 return 0;
45
46 if (!CBB_add_bytes(&protolist, s->internal->alpn_client_proto_list,
47 s->internal->alpn_client_proto_list_len))
48 return 0;
49
50 if (!CBB_flush(cbb))
51 return 0;
52
53 return 1;
54}
55
56int
57tlsext_alpn_clienthello_parse(SSL *s, CBS *cbs, int *alert)
58{
59 CBS proto_name_list, alpn;
60 const unsigned char *selected;
61 unsigned char selected_len;
62 int r;
63
64 if (s->ctx->internal->alpn_select_cb == NULL)
65 return 1;
66
67 if (!CBS_get_u16_length_prefixed(cbs, &alpn))
68 goto err;
69 if (CBS_len(&alpn) < 2)
70 goto err;
71 if (CBS_len(cbs) != 0)
72 goto err;
73
74 CBS_dup(&alpn, &proto_name_list);
75 while (CBS_len(&proto_name_list) > 0) {
76 CBS proto_name;
77
78 if (!CBS_get_u8_length_prefixed(&proto_name_list, &proto_name))
79 goto err;
80 if (CBS_len(&proto_name) == 0)
81 goto err;
82 }
83
84 r = s->ctx->internal->alpn_select_cb(s, &selected, &selected_len,
85 CBS_data(&alpn), CBS_len(&alpn),
86 s->ctx->internal->alpn_select_cb_arg);
87 if (r == SSL_TLSEXT_ERR_OK) {
88 free(S3I(s)->alpn_selected);
89 if ((S3I(s)->alpn_selected = malloc(selected_len)) == NULL) {
90 *alert = SSL_AD_INTERNAL_ERROR;
91 return 0;
92 }
93 memcpy(S3I(s)->alpn_selected, selected, selected_len);
94 S3I(s)->alpn_selected_len = selected_len;
95 }
96
97 return 1;
98
99 err:
100 *alert = SSL_AD_DECODE_ERROR;
101 return 0;
102}
103
104int
105tlsext_alpn_serverhello_needs(SSL *s)
106{
107 return S3I(s)->alpn_selected != NULL;
108}
109
110int
111tlsext_alpn_serverhello_build(SSL *s, CBB *cbb)
112{
113 CBB list, selected;
114
115 if (!CBB_add_u16_length_prefixed(cbb, &list))
116 return 0;
117
118 if (!CBB_add_u8_length_prefixed(&list, &selected))
119 return 0;
120
121 if (!CBB_add_bytes(&selected, S3I(s)->alpn_selected,
122 S3I(s)->alpn_selected_len))
123 return 0;
124
125 if (!CBB_flush(cbb))
126 return 0;
127
128 return 1;
129}
130
131int
132tlsext_alpn_serverhello_parse(SSL *s, CBS *cbs, int *alert)
133{
134 CBS list, proto;
135
136 if (s->internal->alpn_client_proto_list == NULL) {
137 *alert = TLS1_AD_UNSUPPORTED_EXTENSION;
138 return 0;
139 }
140
141 if (!CBS_get_u16_length_prefixed(cbs, &list))
142 goto err;
143 if (CBS_len(cbs) != 0)
144 goto err;
145
146 if (!CBS_get_u8_length_prefixed(&list, &proto))
147 goto err;
148
149 if (CBS_len(&list) != 0)
150 goto err;
151 if (CBS_len(&proto) == 0)
152 goto err;
153
154 if (!CBS_stow(&proto, &(S3I(s)->alpn_selected),
155 &(S3I(s)->alpn_selected_len)))
156 goto err;
157
158 return 1;
159
160 err:
161 *alert = TLS1_AD_DECODE_ERROR;
162 return 0;
163}
26 164
27/* 165/*
28 * Supported Elliptic Curves - RFC 4492 section 5.1.1 166 * Supported Elliptic Curves - RFC 4492 section 5.1.1
@@ -919,6 +1057,15 @@ static struct tls_extension tls_extensions[] = {
919 .serverhello_build = tlsext_sigalgs_serverhello_build, 1057 .serverhello_build = tlsext_sigalgs_serverhello_build,
920 .serverhello_parse = tlsext_sigalgs_serverhello_parse, 1058 .serverhello_parse = tlsext_sigalgs_serverhello_parse,
921 }, 1059 },
1060 {
1061 .type = TLSEXT_TYPE_application_layer_protocol_negotiation,
1062 .clienthello_needs = tlsext_alpn_clienthello_needs,
1063 .clienthello_build = tlsext_alpn_clienthello_build,
1064 .clienthello_parse = tlsext_alpn_clienthello_parse,
1065 .serverhello_needs = tlsext_alpn_serverhello_needs,
1066 .serverhello_build = tlsext_alpn_serverhello_build,
1067 .serverhello_parse = tlsext_alpn_serverhello_parse,
1068 },
922}; 1069};
923 1070
924#define N_TLS_EXTENSIONS (sizeof(tls_extensions) / sizeof(*tls_extensions)) 1071#define N_TLS_EXTENSIONS (sizeof(tls_extensions) / sizeof(*tls_extensions))
diff --git a/src/lib/libssl/ssl_tlsext.h b/src/lib/libssl/ssl_tlsext.h
index bba8bdbea9..21f9bb1bf9 100644
--- a/src/lib/libssl/ssl_tlsext.h
+++ b/src/lib/libssl/ssl_tlsext.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssl_tlsext.h,v 1.8 2017/08/12 23:38:12 beck Exp $ */ 1/* $OpenBSD: ssl_tlsext.h,v 1.9 2017/08/26 20:23:46 doug Exp $ */
2/* 2/*
3 * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> 4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
@@ -16,6 +16,13 @@
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */ 17 */
18 18
19int tlsext_alpn_clienthello_needs(SSL *s);
20int tlsext_alpn_clienthello_build(SSL *s, CBB *cbb);
21int tlsext_alpn_clienthello_parse(SSL *s, CBS *cbs, int *alert);
22int tlsext_alpn_serverhello_needs(SSL *s);
23int tlsext_alpn_serverhello_build(SSL *s, CBB *cbb);
24int tlsext_alpn_serverhello_parse(SSL *s, CBS *cbs, int *alert);
25
19int tlsext_ri_clienthello_needs(SSL *s); 26int tlsext_ri_clienthello_needs(SSL *s);
20int tlsext_ri_clienthello_build(SSL *s, CBB *cbb); 27int tlsext_ri_clienthello_build(SSL *s, CBB *cbb);
21int tlsext_ri_clienthello_parse(SSL *s, CBS *cbs, int *alert); 28int tlsext_ri_clienthello_parse(SSL *s, CBS *cbs, int *alert);
diff --git a/src/lib/libssl/t1_lib.c b/src/lib/libssl/t1_lib.c
index d71067d73c..eb1d96cc11 100644
--- a/src/lib/libssl/t1_lib.c
+++ b/src/lib/libssl/t1_lib.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: t1_lib.c,v 1.134 2017/08/13 21:10:42 bcook Exp $ */ 1/* $OpenBSD: t1_lib.c,v 1.135 2017/08/26 20:23:46 doug Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -687,19 +687,6 @@ ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
687 return NULL; 687 return NULL;
688 ret += len; 688 ret += len;
689 689
690 if (s->internal->alpn_client_proto_list != NULL &&
691 S3I(s)->tmp.finish_md_len == 0) {
692 if ((size_t)(limit - ret) <
693 6 + s->internal->alpn_client_proto_list_len)
694 return (NULL);
695 s2n(TLSEXT_TYPE_application_layer_protocol_negotiation, ret);
696 s2n(2 + s->internal->alpn_client_proto_list_len, ret);
697 s2n(s->internal->alpn_client_proto_list_len, ret);
698 memcpy(ret, s->internal->alpn_client_proto_list,
699 s->internal->alpn_client_proto_list_len);
700 ret += s->internal->alpn_client_proto_list_len;
701 }
702
703#ifndef OPENSSL_NO_SRTP 690#ifndef OPENSSL_NO_SRTP
704 if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)) { 691 if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)) {
705 int el; 692 int el;
@@ -778,20 +765,6 @@ ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
778 } 765 }
779#endif 766#endif
780 767
781 if (S3I(s)->alpn_selected != NULL) {
782 const unsigned char *selected = S3I(s)->alpn_selected;
783 unsigned int len = S3I(s)->alpn_selected_len;
784
785 if ((long)(limit - ret - 4 - 2 - 1 - len) < 0)
786 return (NULL);
787 s2n(TLSEXT_TYPE_application_layer_protocol_negotiation, ret);
788 s2n(3 + len, ret);
789 s2n(1 + len, ret);
790 *ret++ = len;
791 memcpy(ret, selected, len);
792 ret += len;
793 }
794
795 if ((extdatalen = ret - p - 2) == 0) 768 if ((extdatalen = ret - p - 2) == 0)
796 return p; 769 return p;
797 770
@@ -799,71 +772,6 @@ ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
799 return ret; 772 return ret;
800} 773}
801 774
802/*
803 * tls1_alpn_handle_client_hello is called to process the ALPN extension in a
804 * ClientHello.
805 * data: the contents of the extension, not including the type and length.
806 * data_len: the number of bytes in data.
807 * al: a pointer to the alert value to send in the event of a non-zero
808 * return.
809 * returns: 1 on success.
810 */
811static int
812tls1_alpn_handle_client_hello(SSL *s, const unsigned char *data,
813 unsigned int data_len, int *al)
814{
815 CBS cbs, proto_name_list, alpn;
816 const unsigned char *selected;
817 unsigned char selected_len;
818 int r;
819
820 if (s->ctx->internal->alpn_select_cb == NULL)
821 return (1);
822
823 if (data_len < 2)
824 goto parse_error;
825
826 CBS_init(&cbs, data, data_len);
827
828 /*
829 * data should contain a uint16 length followed by a series of 8-bit,
830 * length-prefixed strings.
831 */
832 if (!CBS_get_u16_length_prefixed(&cbs, &alpn) ||
833 CBS_len(&alpn) < 2 ||
834 CBS_len(&cbs) != 0)
835 goto parse_error;
836
837 /* Validate data before sending to callback. */
838 CBS_dup(&alpn, &proto_name_list);
839 while (CBS_len(&proto_name_list) > 0) {
840 CBS proto_name;
841
842 if (!CBS_get_u8_length_prefixed(&proto_name_list, &proto_name) ||
843 CBS_len(&proto_name) == 0)
844 goto parse_error;
845 }
846
847 r = s->ctx->internal->alpn_select_cb(s, &selected, &selected_len,
848 CBS_data(&alpn), CBS_len(&alpn),
849 s->ctx->internal->alpn_select_cb_arg);
850 if (r == SSL_TLSEXT_ERR_OK) {
851 free(S3I(s)->alpn_selected);
852 if ((S3I(s)->alpn_selected = malloc(selected_len)) == NULL) {
853 *al = SSL_AD_INTERNAL_ERROR;
854 return (-1);
855 }
856 memcpy(S3I(s)->alpn_selected, selected, selected_len);
857 S3I(s)->alpn_selected_len = selected_len;
858 }
859
860 return (1);
861
862parse_error:
863 *al = SSL_AD_DECODE_ERROR;
864 return (0);
865}
866
867int 775int
868ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, 776ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
869 int n, int *al) 777 int n, int *al)
@@ -907,14 +815,6 @@ ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
907 if (!tlsext_clienthello_parse_one(s, &cbs, type, al)) 815 if (!tlsext_clienthello_parse_one(s, &cbs, type, al))
908 return 0; 816 return 0;
909 817
910 if (type ==
911 TLSEXT_TYPE_application_layer_protocol_negotiation &&
912 s->ctx->internal->alpn_select_cb != NULL &&
913 S3I(s)->tmp.finish_md_len == 0) {
914 if (tls1_alpn_handle_client_hello(s, data,
915 size, al) != 1)
916 return (0);
917 }
918 /* session ticket processed earlier */ 818 /* session ticket processed earlier */
919#ifndef OPENSSL_NO_SRTP 819#ifndef OPENSSL_NO_SRTP
920 else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_use_srtp) { 820 else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_use_srtp) {
@@ -988,44 +888,6 @@ ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, size_t n, int *al)
988 if (!tlsext_serverhello_parse_one(s, &cbs, type, al)) 888 if (!tlsext_serverhello_parse_one(s, &cbs, type, al))
989 return 0; 889 return 0;
990 890
991 if (type == TLSEXT_TYPE_application_layer_protocol_negotiation) {
992 unsigned int len;
993
994 /* We must have requested it. */
995 if (s->internal->alpn_client_proto_list == NULL) {
996 *al = TLS1_AD_UNSUPPORTED_EXTENSION;
997 return 0;
998 }
999 if (size < 4) {
1000 *al = TLS1_AD_DECODE_ERROR;
1001 return (0);
1002 }
1003
1004 /* The extension data consists of:
1005 * uint16 list_length
1006 * uint8 proto_length;
1007 * uint8 proto[proto_length]; */
1008 len = ((unsigned int)data[0]) << 8 |
1009 ((unsigned int)data[1]);
1010 if (len != (unsigned int)size - 2) {
1011 *al = TLS1_AD_DECODE_ERROR;
1012 return (0);
1013 }
1014 len = data[2];
1015 if (len != (unsigned int)size - 3) {
1016 *al = TLS1_AD_DECODE_ERROR;
1017 return (0);
1018 }
1019 free(S3I(s)->alpn_selected);
1020 S3I(s)->alpn_selected = malloc(len);
1021 if (S3I(s)->alpn_selected == NULL) {
1022 *al = TLS1_AD_INTERNAL_ERROR;
1023 return (0);
1024 }
1025 memcpy(S3I(s)->alpn_selected, data + 3, len);
1026 S3I(s)->alpn_selected_len = len;
1027
1028 }
1029#ifndef OPENSSL_NO_SRTP 891#ifndef OPENSSL_NO_SRTP
1030 else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_use_srtp) { 892 else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_use_srtp) {
1031 if (ssl_parse_serverhello_use_srtp_ext(s, data, 893 if (ssl_parse_serverhello_use_srtp_ext(s, data,
diff --git a/src/regress/lib/libssl/tlsext/tlsexttest.c b/src/regress/lib/libssl/tlsext/tlsexttest.c
index 950588ba47..30bbed9d8d 100644
--- a/src/regress/lib/libssl/tlsext/tlsexttest.c
+++ b/src/regress/lib/libssl/tlsext/tlsexttest.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tlsexttest.c,v 1.12 2017/08/12 23:39:24 beck Exp $ */ 1/* $OpenBSD: tlsexttest.c,v 1.13 2017/08/26 20:23:46 doug Exp $ */
2/* 2/*
3 * Copyright (c) 2017 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2017 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> 4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
@@ -74,6 +74,383 @@ do { \
74} while(0) 74} while(0)
75 75
76/* 76/*
77 * Supported Application-Layer Protocol Negotiation - RFC 7301
78 *
79 * There are already extensive unit tests for this so this just
80 * tests the state info.
81 */
82
83const uint8_t tlsext_alpn_multiple_protos_val[] = {
84 /* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
85 0x08, /* len */
86 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31,
87 /* opaque ProtocolName<1..2^8-1> -- 'stun.nat' */
88 0x09, /* len */
89 0x73, 0x74, 0x75, 0x6e, 0x2e, 0x74, 0x75, 0x72, 0x6e
90};
91
92const uint8_t tlsext_alpn_multiple_protos[] = {
93 /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
94 0x00, 0x13, /* len of all names */
95 /* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
96 0x08, /* len */
97 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31,
98 /* opaque ProtocolName<1..2^8-1> -- 'stun.nat' */
99 0x09, /* len */
100 0x73, 0x74, 0x75, 0x6e, 0x2e, 0x74, 0x75, 0x72, 0x6e
101};
102
103const uint8_t tlsext_alpn_single_proto_val[] = {
104 /* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
105 0x08, /* len */
106 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31
107};
108
109const uint8_t tlsext_alpn_single_proto_name[] = {
110 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 /* 'http/1.1' */
111};
112
113const uint8_t tlsext_alpn_single_proto[] = {
114 /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
115 0x00, 0x09, /* len of all names */
116 /* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
117 0x08, /* len */
118 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31
119};
120
121static int
122test_tlsext_alpn_clienthello(void)
123{
124 SSL_CTX *ssl_ctx = NULL;
125 SSL *ssl = NULL;
126 uint8_t *data = NULL;
127 CBB cbb;
128 CBS cbs;
129 int failure, alert;
130 size_t dlen;
131
132 CBB_init(&cbb, 0);
133
134 failure = 1;
135
136 if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL)
137 errx(1, "failed to create SSL_CTX");
138 if ((ssl = SSL_new(ssl_ctx)) == NULL)
139 errx(1, "failed to create SSL");
140
141 /* By default, we don't need this */
142 if (tlsext_alpn_clienthello_needs(ssl)) {
143 FAIL("clienthello should not need ALPN by default");
144 goto err;
145 }
146
147 /*
148 * Prereqs:
149 * 1) Set s->internal->alpn_client_proto_list
150 * - Using SSL_set_alpn_protos()
151 * 2) We have not finished or renegotiated.
152 * - S3I(s)->tmp.finish_md_len == 0
153 */
154 if (SSL_set_alpn_protos(ssl, tlsext_alpn_single_proto_val,
155 sizeof(tlsext_alpn_single_proto_val)) != 0) {
156 FAIL("should be able to set ALPN to http/1.1");
157 goto err;
158 }
159 if (!tlsext_alpn_clienthello_needs(ssl)) {
160 FAIL("clienthello should need ALPN by now");
161 goto err;
162 }
163
164 /* Make sure we can build the clienthello with a single proto. */
165
166 if (!tlsext_alpn_clienthello_build(ssl, &cbb)) {
167 FAIL("clienthello failed to build ALPN\n");
168 goto err;
169 }
170 if (!CBB_finish(&cbb, &data, &dlen))
171 errx(1, "failed to finish CBB");
172
173 if (dlen != sizeof(tlsext_alpn_single_proto)) {
174 FAIL("got clienthello ALPN with length %zu, "
175 "want length %zu\n", dlen,
176 sizeof(tlsext_alpn_single_proto));
177 compare_data(data, dlen, tlsext_alpn_single_proto,
178 sizeof(tlsext_alpn_single_proto));
179 goto err;
180 }
181 if (memcmp(data, tlsext_alpn_single_proto, dlen) != 0) {
182 FAIL("clienthello ALPN differs:\n");
183 compare_data(data, dlen, tlsext_alpn_single_proto,
184 sizeof(tlsext_alpn_single_proto));
185 goto err;
186 }
187
188 CBB_cleanup(&cbb);
189 CBB_init(&cbb, 0);
190 free(data);
191 data = NULL;
192
193 /* Make sure we can parse the single proto. */
194
195 CBS_init(&cbs, tlsext_alpn_single_proto,
196 sizeof(tlsext_alpn_single_proto));
197 if (!tlsext_alpn_clienthello_parse(ssl, &cbs, &alert)) {
198 FAIL("failed to parse ALPN");
199 goto err;
200 }
201
202 if (ssl->internal->alpn_client_proto_list_len !=
203 sizeof(tlsext_alpn_single_proto_val)) {
204 FAIL("got clienthello ALPN with length %zu, "
205 "want length %zu\n", dlen,
206 sizeof(tlsext_alpn_single_proto_val));
207 compare_data(ssl->internal->alpn_client_proto_list,
208 ssl->internal->alpn_client_proto_list_len,
209 tlsext_alpn_single_proto_val,
210 sizeof(tlsext_alpn_single_proto_val));
211 goto err;
212 }
213 if (memcmp(ssl->internal->alpn_client_proto_list,
214 tlsext_alpn_single_proto_val,
215 sizeof(tlsext_alpn_single_proto_val)) != 0) {
216 FAIL("clienthello ALPN differs:\n");
217 compare_data(data, dlen, tlsext_alpn_single_proto_val,
218 sizeof(tlsext_alpn_single_proto_val));
219 goto err;
220 }
221
222 /* Make sure we can build the clienthello with multiple entries. */
223
224 if (SSL_set_alpn_protos(ssl, tlsext_alpn_multiple_protos_val,
225 sizeof(tlsext_alpn_multiple_protos_val)) != 0) {
226 FAIL("should be able to set ALPN to http/1.1");
227 goto err;
228 }
229 if (!tlsext_alpn_clienthello_needs(ssl)) {
230 FAIL("clienthello should need ALPN by now");
231 goto err;
232 }
233
234 if (!tlsext_alpn_clienthello_build(ssl, &cbb)) {
235 FAIL("clienthello failed to build ALPN\n");
236 goto err;
237 }
238 if (!CBB_finish(&cbb, &data, &dlen))
239 errx(1, "failed to finish CBB");
240
241 if (dlen != sizeof(tlsext_alpn_multiple_protos)) {
242 FAIL("got clienthello ALPN with length %zu, "
243 "want length %zu\n", dlen,
244 sizeof(tlsext_alpn_multiple_protos));
245 compare_data(data, dlen, tlsext_alpn_multiple_protos,
246 sizeof(tlsext_alpn_multiple_protos));
247 goto err;
248 }
249 if (memcmp(data, tlsext_alpn_multiple_protos, dlen) != 0) {
250 FAIL("clienthello ALPN differs:\n");
251 compare_data(data, dlen, tlsext_alpn_multiple_protos,
252 sizeof(tlsext_alpn_multiple_protos));
253 goto err;
254 }
255
256 /* Make sure we can parse multiple protos */
257
258 CBS_init(&cbs, tlsext_alpn_multiple_protos,
259 sizeof(tlsext_alpn_multiple_protos));
260 if (!tlsext_alpn_clienthello_parse(ssl, &cbs, &alert)) {
261 FAIL("failed to parse ALPN");
262 goto err;
263 }
264
265 if (ssl->internal->alpn_client_proto_list_len !=
266 sizeof(tlsext_alpn_multiple_protos_val)) {
267 FAIL("got clienthello ALPN with length %zu, "
268 "want length %zu\n", dlen,
269 sizeof(tlsext_alpn_multiple_protos_val));
270 compare_data(ssl->internal->alpn_client_proto_list,
271 ssl->internal->alpn_client_proto_list_len,
272 tlsext_alpn_multiple_protos_val,
273 sizeof(tlsext_alpn_multiple_protos_val));
274 goto err;
275 }
276 if (memcmp(ssl->internal->alpn_client_proto_list,
277 tlsext_alpn_multiple_protos_val,
278 sizeof(tlsext_alpn_multiple_protos_val)) != 0) {
279 FAIL("clienthello ALPN differs:\n");
280 compare_data(data, dlen, tlsext_alpn_multiple_protos_val,
281 sizeof(tlsext_alpn_multiple_protos_val));
282 goto err;
283 }
284
285 /* Make sure we can remove the list and avoid ALPN */
286
287 free(ssl->internal->alpn_client_proto_list);
288 ssl->internal->alpn_client_proto_list = NULL;
289 ssl->internal->alpn_client_proto_list_len = 0;
290
291 if (tlsext_alpn_clienthello_needs(ssl)) {
292 FAIL("clienthello should need ALPN by default");
293 goto err;
294 }
295
296 failure = 0;
297
298 err:
299 CBB_cleanup(&cbb);
300 SSL_CTX_free(ssl_ctx);
301 SSL_free(ssl);
302 free(data);
303
304 return (failure);
305}
306
307static int
308test_tlsext_alpn_serverhello(void)
309{
310 SSL_CTX *ssl_ctx = NULL;
311 SSL *ssl = NULL;
312 uint8_t *data = NULL;
313 CBB cbb;
314 CBS cbs;
315 int failure, alert;
316 size_t dlen;
317
318 CBB_init(&cbb, 0);
319
320 failure = 1;
321
322 if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL)
323 errx(1, "failed to create SSL_CTX");
324 if ((ssl = SSL_new(ssl_ctx)) == NULL)
325 errx(1, "failed to create SSL");
326
327 /* By default, ALPN isn't needed. */
328 if (tlsext_alpn_serverhello_needs(ssl)) {
329 FAIL("serverhello should not need ALPN by default\n");
330 goto err;
331 }
332
333 /*
334 * The server has a single ALPN selection which is set by
335 * SSL_CTX_set_alpn_select_cb() and calls SSL_select_next_proto().
336 *
337 * This will be a plain name and separate length.
338 */
339 if ((S3I(ssl)->alpn_selected = malloc(sizeof(tlsext_alpn_single_proto_name))) == NULL) {
340 errx(1, "failed to malloc");
341 }
342 memcpy(S3I(ssl)->alpn_selected, tlsext_alpn_single_proto_name,
343 sizeof(tlsext_alpn_single_proto_name));
344 S3I(ssl)->alpn_selected_len = sizeof(tlsext_alpn_single_proto_name);
345
346 if (!tlsext_alpn_serverhello_needs(ssl)) {
347 FAIL("serverhello should need ALPN after a protocol is selected\n");
348 goto err;
349 }
350
351 /* Make sure we can build a serverhello with one protocol */
352
353 if (!tlsext_alpn_serverhello_build(ssl, &cbb)) {
354 FAIL("serverhello should be able to build a response");
355 goto err;
356 }
357 if (!CBB_finish(&cbb, &data, &dlen))
358 errx(1, "failed to finish CBB");
359
360 if (dlen != sizeof(tlsext_alpn_single_proto)) {
361 FAIL("got clienthello ALPN with length %zu, "
362 "want length %zu\n", dlen,
363 sizeof(tlsext_alpn_single_proto));
364 compare_data(data, dlen, tlsext_alpn_single_proto,
365 sizeof(tlsext_alpn_single_proto));
366 goto err;
367 }
368 if (memcmp(data, tlsext_alpn_single_proto, dlen) != 0) {
369 FAIL("clienthello ALPN differs:\n");
370 compare_data(data, dlen, tlsext_alpn_single_proto,
371 sizeof(tlsext_alpn_single_proto));
372 goto err;
373 }
374
375 CBB_cleanup(&cbb);
376 CBB_init(&cbb, 0);
377 free(data);
378 data = NULL;
379
380 /* Make sure we can parse the single proto. */
381
382 CBS_init(&cbs, tlsext_alpn_single_proto,
383 sizeof(tlsext_alpn_single_proto));
384
385 /* Shouldn't be able to parse without requesting */
386 if (tlsext_alpn_serverhello_parse(ssl, &cbs, &alert)) {
387 FAIL("Should only parse serverhello if we requested it");
388 goto err;
389 }
390
391 /* Should be able to parse once requested. */
392 if (SSL_set_alpn_protos(ssl, tlsext_alpn_single_proto_val,
393 sizeof(tlsext_alpn_single_proto_val)) != 0) {
394 FAIL("should be able to set ALPN to http/1.1");
395 goto err;
396 }
397 if (!tlsext_alpn_serverhello_parse(ssl, &cbs, &alert)) {
398 FAIL("Should be able to parse serverhello when we request it");
399 goto err;
400 }
401
402 if (S3I(ssl)->alpn_selected_len !=
403 sizeof(tlsext_alpn_single_proto_name)) {
404 FAIL("got serverhello ALPN with length %zu, "
405 "want length %zu\n", dlen,
406 sizeof(tlsext_alpn_single_proto_name));
407 compare_data(S3I(ssl)->alpn_selected,
408 S3I(ssl)->alpn_selected_len,
409 tlsext_alpn_single_proto_name,
410 sizeof(tlsext_alpn_single_proto_name));
411 goto err;
412 }
413 if (memcmp(S3I(ssl)->alpn_selected,
414 tlsext_alpn_single_proto_name,
415 sizeof(tlsext_alpn_single_proto_name)) != 0) {
416 FAIL("serverhello ALPN differs:\n");
417 compare_data(S3I(ssl)->alpn_selected,
418 S3I(ssl)->alpn_selected_len,
419 tlsext_alpn_single_proto_name,
420 sizeof(tlsext_alpn_single_proto_name));
421 goto err;
422 }
423
424 /*
425 * We should NOT be able to build a serverhello with multiple
426 * protocol names. However, the existing code did not check for this
427 * case because it is passed in as an encoded value.
428 */
429
430 /* Make sure we can remove the list and avoid ALPN */
431
432 free(S3I(ssl)->alpn_selected);
433 S3I(ssl)->alpn_selected = NULL;
434 S3I(ssl)->alpn_selected_len = 0;
435
436 if (tlsext_alpn_serverhello_needs(ssl)) {
437 FAIL("serverhello should need ALPN by default");
438 goto err;
439 }
440
441 failure = 0;
442
443 err:
444 CBB_cleanup(&cbb);
445 SSL_CTX_free(ssl_ctx);
446 SSL_free(ssl);
447 free(data);
448
449 return (failure);
450
451}
452
453/*
77 * Supported Elliptic Curves - RFC 4492 section 5.1.1. 454 * Supported Elliptic Curves - RFC 4492 section 5.1.1.
78 * 455 *
79 * This extension is only used by the client. 456 * This extension is only used by the client.
@@ -1886,6 +2263,9 @@ main(int argc, char **argv)
1886 2263
1887 SSL_library_init(); 2264 SSL_library_init();
1888 2265
2266 failed |= test_tlsext_alpn_clienthello();
2267 failed |= test_tlsext_alpn_serverhello();
2268
1889 failed |= test_tlsext_ec_clienthello(); 2269 failed |= test_tlsext_ec_clienthello();
1890 failed |= test_tlsext_ec_serverhello(); 2270 failed |= test_tlsext_ec_serverhello();
1891 2271