summaryrefslogtreecommitdiff
path: root/src/lib/libssl/ssl_tlsext.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/libssl/ssl_tlsext.c149
1 files changed, 148 insertions, 1 deletions
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))