summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authordoug <>2017-08-26 20:23:46 +0000
committerdoug <>2017-08-26 20:23:46 +0000
commit4d875aa977b8bbe9969527101d0f2d7d67a77b0b (patch)
treed42347fee889bfbea6b518ea0c0bc8a2f6c60bc0 /src/lib
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@
Diffstat (limited to 'src/lib')
-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
4 files changed, 159 insertions, 143 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,