summaryrefslogtreecommitdiff
path: root/src/lib/libssl/ssl_tlsext.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libssl/ssl_tlsext.c')
-rw-r--r--src/lib/libssl/ssl_tlsext.c261
1 files changed, 261 insertions, 0 deletions
diff --git a/src/lib/libssl/ssl_tlsext.c b/src/lib/libssl/ssl_tlsext.c
new file mode 100644
index 0000000000..18ac98103a
--- /dev/null
+++ b/src/lib/libssl/ssl_tlsext.c
@@ -0,0 +1,261 @@
1/* $OpenBSD: ssl_tlsext.c,v 1.1 2017/07/16 18:14:37 jsing Exp $ */
2/*
3 * Copyright (c) 2016, 2017 Joel Sing <jsing@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 "ssl_locl.h"
19
20#include "bytestring.h"
21#include "ssl_tlsext.h"
22
23/*
24 * Server Name Indication - RFC 6066, section 3.
25 */
26int
27tlsext_sni_clienthello_needs(SSL *s)
28{
29 return (s->tlsext_hostname != NULL);
30}
31
32int
33tlsext_sni_clienthello_build(SSL *s, CBB *cbb)
34{
35 CBB server_name_list, host_name;
36
37 if (!CBB_add_u16_length_prefixed(cbb, &server_name_list))
38 return 0;
39 if (!CBB_add_u8(&server_name_list, TLSEXT_NAMETYPE_host_name))
40 return 0;
41 if (!CBB_add_u16_length_prefixed(&server_name_list, &host_name))
42 return 0;
43 if (!CBB_add_bytes(&host_name, (const uint8_t *)s->tlsext_hostname,
44 strlen(s->tlsext_hostname)))
45 return 0;
46 if (!CBB_flush(cbb))
47 return 0;
48
49 return 1;
50}
51
52int
53tlsext_sni_clienthello_parse(SSL *s, CBS *cbs, int *alert)
54{
55 CBS server_name_list, host_name;
56 uint8_t name_type;
57
58 if (!CBS_get_u16_length_prefixed(cbs, &server_name_list))
59 goto err;
60
61 /*
62 * RFC 6066 section 3 forbids multiple host names with the same type.
63 * Additionally, only one type (host_name) is specified.
64 */
65 if (!CBS_get_u8(&server_name_list, &name_type))
66 goto err;
67 if (name_type != TLSEXT_NAMETYPE_host_name)
68 goto err;
69
70 if (!CBS_get_u16_length_prefixed(&server_name_list, &host_name))
71 goto err;
72 if (CBS_len(&host_name) == 0 ||
73 CBS_len(&host_name) > TLSEXT_MAXLEN_host_name ||
74 CBS_contains_zero_byte(&host_name)) {
75 *alert = TLS1_AD_UNRECOGNIZED_NAME;
76 return 0;
77 }
78
79 if (s->internal->hit) {
80 if (s->session->tlsext_hostname == NULL) {
81 *alert = TLS1_AD_UNRECOGNIZED_NAME;
82 return 0;
83 }
84 if (!CBS_mem_equal(&host_name, s->session->tlsext_hostname,
85 strlen(s->session->tlsext_hostname))) {
86 *alert = TLS1_AD_UNRECOGNIZED_NAME;
87 return 0;
88 }
89 } else {
90 if (s->session->tlsext_hostname != NULL)
91 goto err;
92 if (!CBS_strdup(&host_name, &s->session->tlsext_hostname)) {
93 *alert = TLS1_AD_INTERNAL_ERROR;
94 return 0;
95 }
96 }
97
98 if (CBS_len(&server_name_list) != 0)
99 goto err;
100 if (CBS_len(cbs) != 0)
101 goto err;
102
103 return 1;
104
105 err:
106 *alert = SSL_AD_DECODE_ERROR;
107 return 0;
108}
109
110int
111tlsext_sni_serverhello_needs(SSL *s)
112{
113 return (s->session->tlsext_hostname != NULL);
114}
115
116int
117tlsext_sni_serverhello_build(SSL *s, CBB *cbb)
118{
119 return 1;
120}
121
122int
123tlsext_sni_serverhello_parse(SSL *s, CBS *cbs, int *alert)
124{
125 if (s->tlsext_hostname == NULL || CBS_len(cbs) != 0) {
126 *alert = TLS1_AD_UNRECOGNIZED_NAME;
127 return 0;
128 }
129
130 return 1;
131}
132
133struct tls_extension {
134 uint16_t type;
135 int (*clienthello_needs)(SSL *s);
136 int (*clienthello_build)(SSL *s, CBB *cbb);
137 int (*clienthello_parse)(SSL *s, CBS *cbs, int *alert);
138 int (*serverhello_needs)(SSL *s);
139 int (*serverhello_build)(SSL *s, CBB *cbb);
140 int (*serverhello_parse)(SSL *s, CBS *cbs, int *alert);
141};
142
143static struct tls_extension tls_extensions[] = {
144 {
145 .type = TLSEXT_TYPE_server_name,
146 .clienthello_needs = tlsext_sni_clienthello_needs,
147 .clienthello_build = tlsext_sni_clienthello_build,
148 .clienthello_parse = tlsext_sni_clienthello_parse,
149 .serverhello_needs = tlsext_sni_serverhello_needs,
150 .serverhello_build = tlsext_sni_serverhello_build,
151 .serverhello_parse = tlsext_sni_serverhello_parse,
152 },
153};
154
155#define N_TLS_EXTENSIONS (sizeof(tls_extensions) / sizeof(*tls_extensions))
156
157int
158tlsext_clienthello_build(SSL *s, CBB *cbb)
159{
160 struct tls_extension *tlsext;
161 CBB extension_data;
162 size_t i;
163
164 memset(&extension_data, 0, sizeof(extension_data));
165
166 for (i = 0; i < N_TLS_EXTENSIONS; i++) {
167 tlsext = &tls_extensions[i];
168
169 if (!tlsext->clienthello_needs(s))
170 continue;
171
172 if (!CBB_add_u16(cbb, tlsext->type))
173 return 0;
174 if (!CBB_add_u16_length_prefixed(cbb, &extension_data))
175 return 0;
176 if (!tls_extensions[i].clienthello_build(s, &extension_data))
177 return 0;
178 if (!CBB_flush(cbb))
179 return 0;
180 }
181
182 return 1;
183}
184
185int
186tlsext_clienthello_parse_one(SSL *s, CBS *cbs, uint16_t type, int *alert)
187{
188 struct tls_extension *tlsext;
189 size_t i;
190
191 for (i = 0; i < N_TLS_EXTENSIONS; i++) {
192 tlsext = &tls_extensions[i];
193
194 if (tlsext->type != type)
195 continue;
196 if (!tlsext->clienthello_parse(s, cbs, alert))
197 return 0;
198 if (CBS_len(cbs) != 0) {
199 *alert = SSL_AD_DECODE_ERROR;
200 return 0;
201 }
202
203 return 1;
204 }
205
206 /* Not found. */
207 return 2;
208}
209
210int
211tlsext_serverhello_build(SSL *s, CBB *cbb)
212{
213 struct tls_extension *tlsext;
214 CBB extension_data;
215 size_t i;
216
217 memset(&extension_data, 0, sizeof(extension_data));
218
219 for (i = 0; i < N_TLS_EXTENSIONS; i++) {
220 tlsext = &tls_extensions[i];
221
222 if (!tlsext->serverhello_needs(s))
223 continue;
224
225 if (!CBB_add_u16(cbb, tlsext->type))
226 return 0;
227 if (!CBB_add_u16_length_prefixed(cbb, &extension_data))
228 return 0;
229 if (!tlsext->serverhello_build(s, &extension_data))
230 return 0;
231 if (!CBB_flush(cbb))
232 return 0;
233 }
234
235 return 1;
236}
237
238int
239tlsext_serverhello_parse_one(SSL *s, CBS *cbs, uint16_t type, int *alert)
240{
241 struct tls_extension *tlsext;
242 size_t i;
243
244 for (i = 0; i < N_TLS_EXTENSIONS; i++) {
245 tlsext = &tls_extensions[i];
246
247 if (tlsext->type != type)
248 continue;
249 if (!tlsext->serverhello_parse(s, cbs, alert))
250 return 0;
251 if (CBS_len(cbs) != 0) {
252 *alert = SSL_AD_DECODE_ERROR;
253 return 0;
254 }
255
256 return 1;
257 }
258
259 /* Not found. */
260 return 2;
261}