xref: /dflybsd-src/crypto/libressl/ssl/ssl_packet.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: ssl_packet.c,v 1.13 2022/02/05 14:54:10 jsing Exp $ */
272c33676SMaxim Ag /*
372c33676SMaxim Ag  * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
472c33676SMaxim Ag  *
572c33676SMaxim Ag  * Permission to use, copy, modify, and distribute this software for any
672c33676SMaxim Ag  * purpose with or without fee is hereby granted, provided that the above
772c33676SMaxim Ag  * copyright notice and this permission notice appear in all copies.
872c33676SMaxim Ag  *
972c33676SMaxim Ag  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1072c33676SMaxim Ag  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1172c33676SMaxim Ag  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1272c33676SMaxim Ag  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1372c33676SMaxim Ag  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1472c33676SMaxim Ag  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1572c33676SMaxim Ag  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1672c33676SMaxim Ag  */
1772c33676SMaxim Ag 
1872c33676SMaxim Ag #include "bytestring.h"
19*de0e0e4dSAntonio Huete Jimenez #include "ssl_locl.h"
2072c33676SMaxim Ag 
2172c33676SMaxim Ag static int
ssl_is_sslv2_client_hello(CBS * header)2272c33676SMaxim Ag ssl_is_sslv2_client_hello(CBS *header)
2372c33676SMaxim Ag {
2472c33676SMaxim Ag 	uint16_t record_length;
2572c33676SMaxim Ag 	uint8_t message_type;
2672c33676SMaxim Ag 	CBS cbs;
2772c33676SMaxim Ag 
2872c33676SMaxim Ag 	CBS_dup(header, &cbs);
2972c33676SMaxim Ag 
3072c33676SMaxim Ag 	if (!CBS_get_u16(&cbs, &record_length) ||
3172c33676SMaxim Ag 	    !CBS_get_u8(&cbs, &message_type))
3272c33676SMaxim Ag 		return 0;
3372c33676SMaxim Ag 
3472c33676SMaxim Ag 	/*
3572c33676SMaxim Ag 	 * The SSLv2 record length field uses variable length (2 or 3 byte)
3672c33676SMaxim Ag 	 * encoding. Given the size of a client hello, we expect/require the
3772c33676SMaxim Ag 	 * 2-byte form which is indicated by a one in the most significant bit.
3872c33676SMaxim Ag 	 */
3972c33676SMaxim Ag 	if ((record_length & 0x8000) == 0)
4072c33676SMaxim Ag 		return 0;
4172c33676SMaxim Ag 	if ((record_length & ~0x8000) < 3)
4272c33676SMaxim Ag 		return 0;
4372c33676SMaxim Ag 	if (message_type != SSL2_MT_CLIENT_HELLO)
4472c33676SMaxim Ag 		return 0;
4572c33676SMaxim Ag 
4672c33676SMaxim Ag 	return 1;
4772c33676SMaxim Ag }
4872c33676SMaxim Ag 
4972c33676SMaxim Ag static int
ssl_is_sslv3_handshake(CBS * header)5072c33676SMaxim Ag ssl_is_sslv3_handshake(CBS *header)
5172c33676SMaxim Ag {
5272c33676SMaxim Ag 	uint16_t record_version;
5372c33676SMaxim Ag 	uint8_t record_type;
5472c33676SMaxim Ag 	CBS cbs;
5572c33676SMaxim Ag 
5672c33676SMaxim Ag 	CBS_dup(header, &cbs);
5772c33676SMaxim Ag 
5872c33676SMaxim Ag 	if (!CBS_get_u8(&cbs, &record_type) ||
5972c33676SMaxim Ag 	    !CBS_get_u16(&cbs, &record_version))
6072c33676SMaxim Ag 		return 0;
6172c33676SMaxim Ag 
6272c33676SMaxim Ag 	if (record_type != SSL3_RT_HANDSHAKE)
6372c33676SMaxim Ag 		return 0;
6472c33676SMaxim Ag 	if ((record_version >> 8) != SSL3_VERSION_MAJOR)
6572c33676SMaxim Ag 		return 0;
6672c33676SMaxim Ag 
6772c33676SMaxim Ag 	return 1;
6872c33676SMaxim Ag }
6972c33676SMaxim Ag 
7072c33676SMaxim Ag static int
ssl_convert_sslv2_client_hello(SSL * s)7172c33676SMaxim Ag ssl_convert_sslv2_client_hello(SSL *s)
7272c33676SMaxim Ag {
7372c33676SMaxim Ag 	CBB cbb, handshake, client_hello, cipher_suites, compression, session_id;
7472c33676SMaxim Ag 	CBS cbs, challenge, cipher_specs, session;
7572c33676SMaxim Ag 	uint16_t record_length, client_version, cipher_specs_length;
7672c33676SMaxim Ag 	uint16_t session_id_length, challenge_length;
7772c33676SMaxim Ag 	unsigned char *client_random = NULL, *data = NULL;
7872c33676SMaxim Ag 	size_t data_len, pad_len, len;
7972c33676SMaxim Ag 	uint32_t cipher_spec;
8072c33676SMaxim Ag 	uint8_t message_type;
8172c33676SMaxim Ag 	unsigned char *pad;
8272c33676SMaxim Ag 	int ret = -1;
8372c33676SMaxim Ag 	int n;
8472c33676SMaxim Ag 
8572c33676SMaxim Ag 	memset(&cbb, 0, sizeof(cbb));
8672c33676SMaxim Ag 
8772c33676SMaxim Ag 	CBS_init(&cbs, s->internal->packet, SSL3_RT_HEADER_LENGTH);
8872c33676SMaxim Ag 
8972c33676SMaxim Ag 	if (!CBS_get_u16(&cbs, &record_length) ||
9072c33676SMaxim Ag 	    !CBS_get_u8(&cbs, &message_type) ||
9172c33676SMaxim Ag 	    !CBS_get_u16(&cbs, &client_version))
9272c33676SMaxim Ag 		return -1;
9372c33676SMaxim Ag 
9472c33676SMaxim Ag 	/*
9572c33676SMaxim Ag 	 * The SSLv2 record length field uses variable length (2 or 3 byte)
9672c33676SMaxim Ag 	 * encoding. Given the size of a client hello, we expect/require the
9772c33676SMaxim Ag 	 * 2-byte form which is indicated by a one in the most significant bit.
9872c33676SMaxim Ag 	 * Also note that the record length value does not include the bytes
9972c33676SMaxim Ag 	 * used for the record length field.
10072c33676SMaxim Ag 	 */
10172c33676SMaxim Ag 	if ((record_length & 0x8000) == 0)
10272c33676SMaxim Ag 		return -1;
10372c33676SMaxim Ag 	record_length &= ~0x8000;
10472c33676SMaxim Ag 	if (record_length < SSL3_RT_HEADER_LENGTH - 2)
10572c33676SMaxim Ag 		return -1;
10672c33676SMaxim Ag 	if (message_type != SSL2_MT_CLIENT_HELLO)
10772c33676SMaxim Ag 		return -1;
10872c33676SMaxim Ag 
10972c33676SMaxim Ag 	if (record_length < 9) {
11072c33676SMaxim Ag 		SSLerror(s, SSL_R_RECORD_LENGTH_MISMATCH);
11172c33676SMaxim Ag 		return -1;
11272c33676SMaxim Ag 	}
11372c33676SMaxim Ag 	if (record_length > 4096) {
11472c33676SMaxim Ag 		SSLerror(s, SSL_R_RECORD_TOO_LARGE);
11572c33676SMaxim Ag 		return -1;
11672c33676SMaxim Ag 	}
11772c33676SMaxim Ag 
11872c33676SMaxim Ag 	n = ssl3_packet_extend(s, record_length + 2);
11972c33676SMaxim Ag 	if (n != record_length + 2)
12072c33676SMaxim Ag 		return n;
12172c33676SMaxim Ag 
12272c33676SMaxim Ag 	tls1_transcript_record(s, s->internal->packet + 2,
12372c33676SMaxim Ag 	    s->internal->packet_length - 2);
12472c33676SMaxim Ag 	s->internal->mac_packet = 0;
12572c33676SMaxim Ag 
12672c33676SMaxim Ag 	if (s->internal->msg_callback)
12772c33676SMaxim Ag 		s->internal->msg_callback(0, SSL2_VERSION, 0,
12872c33676SMaxim Ag 		    s->internal->packet + 2, s->internal->packet_length - 2, s,
12972c33676SMaxim Ag 		    s->internal->msg_callback_arg);
13072c33676SMaxim Ag 
13172c33676SMaxim Ag 	/* Decode the SSLv2 record containing the client hello. */
13272c33676SMaxim Ag 	CBS_init(&cbs, s->internal->packet, s->internal->packet_length);
13372c33676SMaxim Ag 
13472c33676SMaxim Ag 	if (!CBS_get_u16(&cbs, &record_length))
13572c33676SMaxim Ag 		return -1;
13672c33676SMaxim Ag 	if (!CBS_get_u8(&cbs, &message_type))
13772c33676SMaxim Ag 		return -1;
13872c33676SMaxim Ag 	if (!CBS_get_u16(&cbs, &client_version))
13972c33676SMaxim Ag 		return -1;
14072c33676SMaxim Ag 	if (!CBS_get_u16(&cbs, &cipher_specs_length))
14172c33676SMaxim Ag 		return -1;
14272c33676SMaxim Ag 	if (!CBS_get_u16(&cbs, &session_id_length))
14372c33676SMaxim Ag 		return -1;
14472c33676SMaxim Ag 	if (!CBS_get_u16(&cbs, &challenge_length))
14572c33676SMaxim Ag 		return -1;
14672c33676SMaxim Ag 	if (!CBS_get_bytes(&cbs, &cipher_specs, cipher_specs_length))
14772c33676SMaxim Ag 		return -1;
14872c33676SMaxim Ag 	if (!CBS_get_bytes(&cbs, &session, session_id_length))
14972c33676SMaxim Ag 		return -1;
15072c33676SMaxim Ag 	if (!CBS_get_bytes(&cbs, &challenge, challenge_length))
15172c33676SMaxim Ag 		return -1;
15272c33676SMaxim Ag 	if (CBS_len(&cbs) != 0) {
15372c33676SMaxim Ag 		SSLerror(s, SSL_R_RECORD_LENGTH_MISMATCH);
15472c33676SMaxim Ag 		return -1;
15572c33676SMaxim Ag 	}
15672c33676SMaxim Ag 
15772c33676SMaxim Ag 	/*
15872c33676SMaxim Ag 	 * Convert SSLv2 challenge to SSLv3/TLS client random, by truncating or
15972c33676SMaxim Ag 	 * left-padding with zero bytes.
16072c33676SMaxim Ag 	 */
16172c33676SMaxim Ag 	if ((client_random = malloc(SSL3_RANDOM_SIZE)) == NULL)
16272c33676SMaxim Ag 		goto err;
16372c33676SMaxim Ag 	if (!CBB_init_fixed(&cbb, client_random, SSL3_RANDOM_SIZE))
16472c33676SMaxim Ag 		goto err;
16572c33676SMaxim Ag 	if ((len = CBS_len(&challenge)) > SSL3_RANDOM_SIZE)
16672c33676SMaxim Ag 		len = SSL3_RANDOM_SIZE;
16772c33676SMaxim Ag 	pad_len = SSL3_RANDOM_SIZE - len;
16872c33676SMaxim Ag 	if (!CBB_add_space(&cbb, &pad, pad_len))
16972c33676SMaxim Ag 		goto err;
17072c33676SMaxim Ag 	memset(pad, 0, pad_len);
17172c33676SMaxim Ag 	if (!CBB_add_bytes(&cbb, CBS_data(&challenge), len))
17272c33676SMaxim Ag 		goto err;
17372c33676SMaxim Ag 	if (!CBB_finish(&cbb, NULL, NULL))
17472c33676SMaxim Ag 		goto err;
17572c33676SMaxim Ag 
17672c33676SMaxim Ag 	/* Build SSLv3/TLS record with client hello. */
17772c33676SMaxim Ag 	if (!CBB_init(&cbb, SSL3_RT_MAX_PLAIN_LENGTH))
17872c33676SMaxim Ag 		goto err;
17972c33676SMaxim Ag 	if (!CBB_add_u8(&cbb, SSL3_RT_HANDSHAKE))
18072c33676SMaxim Ag 		goto err;
18172c33676SMaxim Ag 	if (!CBB_add_u16(&cbb, 0x0301))
18272c33676SMaxim Ag 		goto err;
18372c33676SMaxim Ag 	if (!CBB_add_u16_length_prefixed(&cbb, &handshake))
18472c33676SMaxim Ag 		goto err;
18572c33676SMaxim Ag 	if (!CBB_add_u8(&handshake, SSL3_MT_CLIENT_HELLO))
18672c33676SMaxim Ag 		goto err;
18772c33676SMaxim Ag 	if (!CBB_add_u24_length_prefixed(&handshake, &client_hello))
18872c33676SMaxim Ag 		goto err;
18972c33676SMaxim Ag 	if (!CBB_add_u16(&client_hello, client_version))
19072c33676SMaxim Ag 		goto err;
19172c33676SMaxim Ag 	if (!CBB_add_bytes(&client_hello, client_random, SSL3_RANDOM_SIZE))
19272c33676SMaxim Ag 		goto err;
19372c33676SMaxim Ag 	if (!CBB_add_u8_length_prefixed(&client_hello, &session_id))
19472c33676SMaxim Ag 		goto err;
19572c33676SMaxim Ag 	if (!CBB_add_u16_length_prefixed(&client_hello, &cipher_suites))
19672c33676SMaxim Ag 		goto err;
19772c33676SMaxim Ag 	while (CBS_len(&cipher_specs) > 0) {
19872c33676SMaxim Ag 		if (!CBS_get_u24(&cipher_specs, &cipher_spec))
19972c33676SMaxim Ag 			goto err;
20072c33676SMaxim Ag 		if ((cipher_spec & 0xff0000) != 0)
20172c33676SMaxim Ag 			continue;
20272c33676SMaxim Ag 		if (!CBB_add_u16(&cipher_suites, cipher_spec & 0xffff))
20372c33676SMaxim Ag 			goto err;
20472c33676SMaxim Ag 	}
20572c33676SMaxim Ag 	if (!CBB_add_u8_length_prefixed(&client_hello, &compression))
20672c33676SMaxim Ag 		goto err;
20772c33676SMaxim Ag 	if (!CBB_add_u8(&compression, 0))
20872c33676SMaxim Ag 		goto err;
20972c33676SMaxim Ag 	if (!CBB_finish(&cbb, &data, &data_len))
21072c33676SMaxim Ag 		goto err;
21172c33676SMaxim Ag 
212*de0e0e4dSAntonio Huete Jimenez 	if (data_len > s->s3->rbuf.len)
21372c33676SMaxim Ag 		goto err;
21472c33676SMaxim Ag 
215*de0e0e4dSAntonio Huete Jimenez 	s->internal->packet = s->s3->rbuf.buf;
21672c33676SMaxim Ag 	s->internal->packet_length = data_len;
21772c33676SMaxim Ag 	memcpy(s->internal->packet, data, data_len);
21872c33676SMaxim Ag 	ret = 1;
21972c33676SMaxim Ag 
22072c33676SMaxim Ag  err:
22172c33676SMaxim Ag 	CBB_cleanup(&cbb);
22272c33676SMaxim Ag 	free(client_random);
22372c33676SMaxim Ag 	free(data);
22472c33676SMaxim Ag 
22572c33676SMaxim Ag 	return (ret);
22672c33676SMaxim Ag }
22772c33676SMaxim Ag 
22872c33676SMaxim Ag /*
22972c33676SMaxim Ag  * Potentially do legacy processing on the first packet received by a TLS
23072c33676SMaxim Ag  * server. We return 1 if we want SSLv3/TLS record processing to continue
23172c33676SMaxim Ag  * normally, otherwise we must set an SSLerr and return -1.
23272c33676SMaxim Ag  */
23372c33676SMaxim Ag int
ssl_server_legacy_first_packet(SSL * s)23472c33676SMaxim Ag ssl_server_legacy_first_packet(SSL *s)
23572c33676SMaxim Ag {
23672c33676SMaxim Ag 	uint16_t min_version;
23772c33676SMaxim Ag 	const char *data;
23872c33676SMaxim Ag 	CBS header;
23972c33676SMaxim Ag 
240*de0e0e4dSAntonio Huete Jimenez 	if (SSL_is_dtls(s))
24172c33676SMaxim Ag 		return 1;
24272c33676SMaxim Ag 
24372c33676SMaxim Ag 	CBS_init(&header, s->internal->packet, SSL3_RT_HEADER_LENGTH);
24472c33676SMaxim Ag 
24572c33676SMaxim Ag 	if (ssl_is_sslv3_handshake(&header) == 1)
24672c33676SMaxim Ag 		return 1;
24772c33676SMaxim Ag 
24872c33676SMaxim Ag 	/* Only continue if this is not a version locked method. */
249*de0e0e4dSAntonio Huete Jimenez 	if (s->method->min_tls_version == s->method->max_tls_version)
25072c33676SMaxim Ag 		return 1;
25172c33676SMaxim Ag 
25272c33676SMaxim Ag 	if (ssl_is_sslv2_client_hello(&header) == 1) {
25372c33676SMaxim Ag 		/* Only permit SSLv2 client hellos if TLSv1.0 is enabled. */
254*de0e0e4dSAntonio Huete Jimenez 		if (ssl_enabled_tls_version_range(s, &min_version, NULL) != 1) {
25572c33676SMaxim Ag 			SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE);
25672c33676SMaxim Ag 			return -1;
25772c33676SMaxim Ag 		}
25872c33676SMaxim Ag 		if (min_version > TLS1_VERSION)
25972c33676SMaxim Ag 			return 1;
26072c33676SMaxim Ag 
26172c33676SMaxim Ag 		if (ssl_convert_sslv2_client_hello(s) != 1) {
26272c33676SMaxim Ag 			SSLerror(s, SSL_R_BAD_PACKET_LENGTH);
26372c33676SMaxim Ag 			return -1;
26472c33676SMaxim Ag 		}
26572c33676SMaxim Ag 
26672c33676SMaxim Ag 		return 1;
26772c33676SMaxim Ag 	}
26872c33676SMaxim Ag 
26972c33676SMaxim Ag 	/* Ensure that we have SSL3_RT_HEADER_LENGTH (5 bytes) of the packet. */
27072c33676SMaxim Ag 	if (CBS_len(&header) != SSL3_RT_HEADER_LENGTH) {
27172c33676SMaxim Ag 		SSLerror(s, ERR_R_INTERNAL_ERROR);
27272c33676SMaxim Ag 		return -1;
27372c33676SMaxim Ag 	}
27472c33676SMaxim Ag 	data = (const char *)CBS_data(&header);
27572c33676SMaxim Ag 
27672c33676SMaxim Ag 	/* Is this a cleartext protocol? */
27772c33676SMaxim Ag 	if (strncmp("GET ", data, 4) == 0 ||
27872c33676SMaxim Ag 	    strncmp("POST ", data, 5) == 0 ||
27972c33676SMaxim Ag 	    strncmp("HEAD ", data, 5) == 0 ||
28072c33676SMaxim Ag 	    strncmp("PUT ", data, 4) == 0) {
28172c33676SMaxim Ag 		SSLerror(s, SSL_R_HTTP_REQUEST);
28272c33676SMaxim Ag 		return -1;
28372c33676SMaxim Ag 	}
28472c33676SMaxim Ag 	if (strncmp("CONNE", data, 5) == 0) {
28572c33676SMaxim Ag 		SSLerror(s, SSL_R_HTTPS_PROXY_REQUEST);
28672c33676SMaxim Ag 		return -1;
28772c33676SMaxim Ag 	}
28872c33676SMaxim Ag 
28972c33676SMaxim Ag 	SSLerror(s, SSL_R_UNKNOWN_PROTOCOL);
29072c33676SMaxim Ag 
29172c33676SMaxim Ag 	return -1;
29272c33676SMaxim Ag }
293