1/* $OpenBSD: ssl_packet.c,v 1.15 2022/11/26 16:08:56 tb 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 "bytestring.h"
19#include "ssl_local.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 = NULL, *data = NULL;
78	size_t data_len, pad_len, len;
79	uint32_t cipher_spec;
80	uint8_t message_type;
81	unsigned char *pad;
82	int ret = -1;
83	int n;
84
85	memset(&cbb, 0, sizeof(cbb));
86
87	CBS_init(&cbs, s->packet, SSL3_RT_HEADER_LENGTH);
88
89	if (!CBS_get_u16(&cbs, &record_length) ||
90	    !CBS_get_u8(&cbs, &message_type) ||
91	    !CBS_get_u16(&cbs, &client_version))
92		return -1;
93
94	/*
95	 * The SSLv2 record length field uses variable length (2 or 3 byte)
96	 * encoding. Given the size of a client hello, we expect/require the
97	 * 2-byte form which is indicated by a one in the most significant bit.
98	 * Also note that the record length value does not include the bytes
99	 * used for the record length field.
100	 */
101	if ((record_length & 0x8000) == 0)
102		return -1;
103	record_length &= ~0x8000;
104	if (record_length < SSL3_RT_HEADER_LENGTH - 2)
105		return -1;
106	if (message_type != SSL2_MT_CLIENT_HELLO)
107		return -1;
108
109	if (record_length < 9) {
110		SSLerror(s, SSL_R_RECORD_LENGTH_MISMATCH);
111		return -1;
112	}
113	if (record_length > 4096) {
114		SSLerror(s, 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_transcript_record(s, s->packet + 2,
123	    s->packet_length - 2);
124	s->mac_packet = 0;
125
126	if (s->msg_callback)
127		s->msg_callback(0, SSL2_VERSION, 0,
128		    s->packet + 2, s->packet_length - 2, s,
129		    s->msg_callback_arg);
130
131	/* Decode the SSLv2 record containing the client hello. */
132	CBS_init(&cbs, s->packet, s->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		SSLerror(s, SSL_R_RECORD_LENGTH_MISMATCH);
154		return -1;
155	}
156
157	/*
158	 * Convert SSLv2 challenge to SSLv3/TLS client random, by truncating or
159	 * left-padding with zero bytes.
160	 */
161	if ((client_random = malloc(SSL3_RANDOM_SIZE)) == NULL)
162		goto err;
163	if (!CBB_init_fixed(&cbb, client_random, SSL3_RANDOM_SIZE))
164		goto err;
165	if ((len = CBS_len(&challenge)) > SSL3_RANDOM_SIZE)
166		len = SSL3_RANDOM_SIZE;
167	pad_len = SSL3_RANDOM_SIZE - len;
168	if (!CBB_add_space(&cbb, &pad, pad_len))
169		goto err;
170	memset(pad, 0, pad_len);
171	if (!CBB_add_bytes(&cbb, CBS_data(&challenge), len))
172		goto err;
173	if (!CBB_finish(&cbb, NULL, NULL))
174		goto err;
175
176	/* Build SSLv3/TLS record with client hello. */
177	if (!CBB_init(&cbb, SSL3_RT_MAX_PLAIN_LENGTH))
178		goto err;
179	if (!CBB_add_u8(&cbb, SSL3_RT_HANDSHAKE))
180		goto err;
181	if (!CBB_add_u16(&cbb, 0x0301))
182		goto err;
183	if (!CBB_add_u16_length_prefixed(&cbb, &handshake))
184		goto err;
185	if (!CBB_add_u8(&handshake, SSL3_MT_CLIENT_HELLO))
186		goto err;
187	if (!CBB_add_u24_length_prefixed(&handshake, &client_hello))
188		goto err;
189	if (!CBB_add_u16(&client_hello, client_version))
190		goto err;
191	if (!CBB_add_bytes(&client_hello, client_random, SSL3_RANDOM_SIZE))
192		goto err;
193	if (!CBB_add_u8_length_prefixed(&client_hello, &session_id))
194		goto err;
195	if (!CBB_add_u16_length_prefixed(&client_hello, &cipher_suites))
196		goto err;
197	while (CBS_len(&cipher_specs) > 0) {
198		if (!CBS_get_u24(&cipher_specs, &cipher_spec))
199			goto err;
200		if ((cipher_spec & 0xff0000) != 0)
201			continue;
202		if (!CBB_add_u16(&cipher_suites, cipher_spec & 0xffff))
203			goto err;
204	}
205	if (!CBB_add_u8_length_prefixed(&client_hello, &compression))
206		goto err;
207	if (!CBB_add_u8(&compression, 0))
208		goto err;
209	if (!CBB_finish(&cbb, &data, &data_len))
210		goto err;
211
212	if (data_len > s->s3->rbuf.len)
213		goto err;
214
215	s->packet = s->s3->rbuf.buf;
216	s->packet_length = data_len;
217	memcpy(s->packet, data, data_len);
218	ret = 1;
219
220 err:
221	CBB_cleanup(&cbb);
222	free(client_random);
223	free(data);
224
225	return (ret);
226}
227
228/*
229 * Potentially do legacy processing on the first packet received by a TLS
230 * server. We return 1 if we want SSLv3/TLS record processing to continue
231 * normally, otherwise we must set an SSLerr and return -1.
232 */
233int
234ssl_server_legacy_first_packet(SSL *s)
235{
236	uint16_t min_version;
237	const char *data;
238	CBS header;
239
240	if (SSL_is_dtls(s))
241		return 1;
242
243	CBS_init(&header, s->packet, SSL3_RT_HEADER_LENGTH);
244
245	if (ssl_is_sslv3_handshake(&header) == 1)
246		return 1;
247
248	/* Only continue if this is not a version locked method. */
249	if (s->method->min_tls_version == s->method->max_tls_version)
250		return 1;
251
252	if (ssl_is_sslv2_client_hello(&header) == 1) {
253		/* Only permit SSLv2 client hellos if TLSv1.0 is enabled. */
254		if (ssl_enabled_tls_version_range(s, &min_version, NULL) != 1) {
255			SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE);
256			return -1;
257		}
258		if (min_version > TLS1_VERSION)
259			return 1;
260
261		if (ssl_convert_sslv2_client_hello(s) != 1) {
262			SSLerror(s, SSL_R_BAD_PACKET_LENGTH);
263			return -1;
264		}
265
266		return 1;
267	}
268
269	/* Ensure that we have SSL3_RT_HEADER_LENGTH (5 bytes) of the packet. */
270	if (CBS_len(&header) != SSL3_RT_HEADER_LENGTH) {
271		SSLerror(s, ERR_R_INTERNAL_ERROR);
272		return -1;
273	}
274	data = (const char *)CBS_data(&header);
275
276	/* Is this a cleartext protocol? */
277	if (strncmp("GET ", data, 4) == 0 ||
278	    strncmp("POST ", data, 5) == 0 ||
279	    strncmp("HEAD ", data, 5) == 0 ||
280	    strncmp("PUT ", data, 4) == 0) {
281		SSLerror(s, SSL_R_HTTP_REQUEST);
282		return -1;
283	}
284	if (strncmp("CONNE", data, 5) == 0) {
285		SSLerror(s, SSL_R_HTTPS_PROXY_REQUEST);
286		return -1;
287	}
288
289	SSLerror(s, SSL_R_UNKNOWN_PROTOCOL);
290
291	return -1;
292}
293