summaryrefslogtreecommitdiff
path: root/src/lib/libssl/ssl_packet.c
diff options
context:
space:
mode:
authorjsing <>2017-01-26 05:31:25 +0000
committerjsing <>2017-01-26 05:31:25 +0000
commit9366f4ef0d67a19fe5eca3feedbc756a4a8966b2 (patch)
tree4e54623d2ff33c8bd1295cf166bf8253188d9d34 /src/lib/libssl/ssl_packet.c
parentc7118cf7a1b4ff8cec6c52fba26ecfbfba0d7919 (diff)
downloadopenbsd-9366f4ef0d67a19fe5eca3feedbc756a4a8966b2.tar.gz
openbsd-9366f4ef0d67a19fe5eca3feedbc756a4a8966b2.tar.bz2
openbsd-9366f4ef0d67a19fe5eca3feedbc756a4a8966b2.zip
Merge the client/server version negotiation into the existing (currently
fixed version) client/server code. ok beck@
Diffstat (limited to 'src/lib/libssl/ssl_packet.c')
-rw-r--r--src/lib/libssl/ssl_packet.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/src/lib/libssl/ssl_packet.c b/src/lib/libssl/ssl_packet.c
new file mode 100644
index 0000000000..0c5b4c463b
--- /dev/null
+++ b/src/lib/libssl/ssl_packet.c
@@ -0,0 +1,278 @@
1/*
2 * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "ssl_locl.h"
18
19#include "bytestring.h"
20
21static int
22ssl_is_sslv2_client_hello(CBS *header)
23{
24 uint16_t record_length;
25 uint8_t message_type;
26 CBS cbs;
27
28 CBS_dup(header, &cbs);
29
30 if (!CBS_get_u16(&cbs, &record_length) ||
31 !CBS_get_u8(&cbs, &message_type))
32 return 0;
33
34 /*
35 * The SSLv2 record length field uses variable length (2 or 3 byte)
36 * encoding. Given the size of a client hello, we expect/require the
37 * 2-byte form which is indicated by a one in the most significant bit.
38 */
39 if ((record_length & 0x8000) == 0)
40 return 0;
41 if ((record_length & ~0x8000) < 3)
42 return 0;
43 if (message_type != SSL2_MT_CLIENT_HELLO)
44 return 0;
45
46 return 1;
47}
48
49static int
50ssl_is_sslv3_handshake(CBS *header)
51{
52 uint16_t record_version;
53 uint8_t record_type;
54 CBS cbs;
55
56 CBS_dup(header, &cbs);
57
58 if (!CBS_get_u8(&cbs, &record_type) ||
59 !CBS_get_u16(&cbs, &record_version))
60 return 0;
61
62 if (record_type != SSL3_RT_HANDSHAKE)
63 return 0;
64 if ((record_version >> 8) != SSL3_VERSION_MAJOR)
65 return 0;
66
67 return 1;
68}
69
70static int
71ssl_convert_sslv2_client_hello(SSL *s)
72{
73 CBB cbb, handshake, client_hello, cipher_suites, compression, session_id;
74 CBS cbs, challenge, cipher_specs, session;
75 uint16_t record_length, client_version, cipher_specs_length;
76 uint16_t session_id_length, challenge_length;
77 unsigned char *client_random, *data = NULL;
78 uint32_t cipher_spec;
79 uint8_t message_type;
80 size_t data_len;
81 int rv = -1;
82 int n;
83
84 memset(&cbb, 0, sizeof(cbb));
85
86 CBS_init(&cbs, s->internal->packet, SSL3_RT_HEADER_LENGTH);
87
88 if (!CBS_get_u16(&cbs, &record_length) ||
89 !CBS_get_u8(&cbs, &message_type) ||
90 !CBS_get_u16(&cbs, &client_version))
91 return -1;
92
93 /*
94 * The SSLv2 record length field uses variable length (2 or 3 byte)
95 * encoding. Given the size of a client hello, we expect/require the
96 * 2-byte form which is indicated by a one in the most significant bit.
97 * Also note that the record length value does not include the bytes
98 * used for the record length field.
99 */
100 if ((record_length & 0x8000) == 0)
101 return -1;
102 record_length &= ~0x8000;
103 if (record_length < SSL3_RT_HEADER_LENGTH - 2)
104 return -1;
105 if (message_type != SSL2_MT_CLIENT_HELLO)
106 return -1;
107
108 if (record_length < 9) {
109 SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,
110 SSL_R_RECORD_LENGTH_MISMATCH);
111 return -1;
112 }
113 if (record_length > 4096) {
114 SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, SSL_R_RECORD_TOO_LARGE);
115 return -1;
116 }
117
118 n = ssl3_packet_extend(s, record_length + 2);
119 if (n != record_length + 2)
120 return n;
121
122 tls1_finish_mac(s, s->internal->packet + 2,
123 s->internal->packet_length - 2);
124 s->internal->mac_packet = 0;
125
126 if (s->internal->msg_callback)
127 s->internal->msg_callback(0, SSL2_VERSION, 0,
128 s->internal->packet + 2, s->internal->packet_length - 2, s,
129 s->internal->msg_callback_arg);
130
131 /* Decode the SSLv2 record containing the client hello. */
132 CBS_init(&cbs, s->internal->packet, s->internal->packet_length);
133
134 if (!CBS_get_u16(&cbs, &record_length))
135 return -1;
136 if (!CBS_get_u8(&cbs, &message_type))
137 return -1;
138 if (!CBS_get_u16(&cbs, &client_version))
139 return -1;
140 if (!CBS_get_u16(&cbs, &cipher_specs_length))
141 return -1;
142 if (!CBS_get_u16(&cbs, &session_id_length))
143 return -1;
144 if (!CBS_get_u16(&cbs, &challenge_length))
145 return -1;
146 if (!CBS_get_bytes(&cbs, &cipher_specs, cipher_specs_length))
147 return -1;
148 if (!CBS_get_bytes(&cbs, &session, session_id_length))
149 return -1;
150 if (!CBS_get_bytes(&cbs, &challenge, challenge_length))
151 return -1;
152 if (CBS_len(&cbs) != 0) {
153 SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,
154 SSL_R_RECORD_LENGTH_MISMATCH);
155 return -1;
156 }
157
158 /* Build SSLv3/TLS record with client hello. */
159 if (!CBB_init(&cbb, SSL3_RT_MAX_PLAIN_LENGTH))
160 goto err;
161 if (!CBB_add_u8(&cbb, SSL3_RT_HANDSHAKE))
162 goto err;
163 if (!CBB_add_u16(&cbb, 0x0301))
164 goto err;
165 if (!CBB_add_u16_length_prefixed(&cbb, &handshake))
166 goto err;
167 if (!CBB_add_u8(&handshake, SSL3_MT_CLIENT_HELLO))
168 goto err;
169 if (!CBB_add_u24_length_prefixed(&handshake, &client_hello))
170 goto err;
171 if (!CBB_add_u16(&client_hello, client_version))
172 goto err;
173 if (!CBB_add_space(&client_hello, &client_random, SSL3_RANDOM_SIZE))
174 goto err;
175 memset(client_random, 0, SSL3_RANDOM_SIZE);
176 if (!CBS_write_bytes(&challenge, client_random, SSL3_RANDOM_SIZE, NULL))
177 goto err;
178 if (!CBB_add_u8_length_prefixed(&client_hello, &session_id))
179 goto err;
180 if (!CBB_add_u16_length_prefixed(&client_hello, &cipher_suites))
181 goto err;
182 while (CBS_len(&cipher_specs) > 0) {
183 if (!CBS_get_u24(&cipher_specs, &cipher_spec))
184 goto err;
185 if ((cipher_spec & 0xff0000) != 0)
186 continue;
187 if (!CBB_add_u16(&cipher_suites, cipher_spec & 0xffff))
188 goto err;
189 }
190 if (!CBB_add_u8_length_prefixed(&client_hello, &compression))
191 goto err;
192 if (!CBB_add_u8(&compression, 0))
193 goto err;
194 if (!CBB_finish(&cbb, &data, &data_len))
195 goto err;
196
197 if (data_len > s->s3->rbuf.len)
198 goto err;
199
200 s->internal->packet = s->s3->rbuf.buf;
201 s->internal->packet_length = data_len;
202 memcpy(s->internal->packet, data, data_len);
203 rv = 1;
204
205 err:
206 CBB_cleanup(&cbb);
207 free(data);
208
209 return (rv);
210}
211
212/*
213 * Potentially do legacy processing on the first packet received by a TLS
214 * server. We return 1 if we want SSLv3/TLS record processing to continue
215 * normally, otherwise we must set an SSLerr and return -1.
216 */
217int
218ssl_server_legacy_first_packet(SSL *s)
219{
220 uint16_t min_version;
221 const char *data;
222 CBS header;
223
224 if (SSL_IS_DTLS(s))
225 return 1;
226
227 CBS_init(&header, s->internal->packet, SSL3_RT_HEADER_LENGTH);
228
229 if (ssl_is_sslv3_handshake(&header) == 1)
230 return 1;
231
232 /* Only continue if this is not a version locked method. */
233 if (s->method->internal->min_version == s->method->internal->max_version)
234 return 1;
235
236 if (ssl_is_sslv2_client_hello(&header) == 1) {
237 /* Only permit SSLv2 client hellos if TLSv1.0 is enabled. */
238 if (ssl_enabled_version_range(s, &min_version, NULL) != 1) {
239 SSLerr(SSL_F_SSL23_CLIENT_HELLO,
240 SSL_R_NO_PROTOCOLS_AVAILABLE);
241 return -1;
242 }
243 if (min_version > TLS1_VERSION)
244 return 1;
245
246 if (ssl_convert_sslv2_client_hello(s) != 1) {
247 SSLerr(SSL_F_SSL23_CLIENT_HELLO,
248 SSL_R_BAD_PACKET_LENGTH);
249 return -1;
250 }
251
252 return 1;
253 }
254
255 /* Ensure that we have SSL3_RT_HEADER_LENGTH (5 bytes) of the packet. */
256 if (CBS_len(&header) != SSL3_RT_HEADER_LENGTH) {
257 SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
258 return -1;
259 }
260 data = (const char *)CBS_data(&header);
261
262 /* Is this a cleartext protocol? */
263 if (strncmp("GET ", data, 4) == 0 ||
264 strncmp("POST ", data, 5) == 0 ||
265 strncmp("HEAD ", data, 5) == 0 ||
266 strncmp("PUT ", data, 4) == 0) {
267 SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, SSL_R_HTTP_REQUEST);
268 return -1;
269 }
270 if (strncmp("CONNE", data, 5) == 0) {
271 SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, SSL_R_HTTPS_PROXY_REQUEST);
272 return -1;
273 }
274
275 SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
276
277 return -1;
278}