xref: /dflybsd-src/crypto/libressl/ssl/ssl_versions.c (revision 8edacedfc4a3bc9ac4f463b53f61cb4a6eb8d031)
1*8edacedfSDaniel Fojt /* $OpenBSD: ssl_versions.c,v 1.6 2020/05/31 18:03:32 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 "ssl_locl.h"
1972c33676SMaxim Ag 
2072c33676SMaxim Ag static int
2172c33676SMaxim Ag ssl_clamp_version_range(uint16_t *min_ver, uint16_t *max_ver,
2272c33676SMaxim Ag     uint16_t clamp_min, uint16_t clamp_max)
2372c33676SMaxim Ag {
2472c33676SMaxim Ag 	if (clamp_min > clamp_max || *min_ver > *max_ver)
2572c33676SMaxim Ag 		return 0;
2672c33676SMaxim Ag 	if (clamp_max < *min_ver || clamp_min > *max_ver)
2772c33676SMaxim Ag 		return 0;
2872c33676SMaxim Ag 
2972c33676SMaxim Ag 	if (*min_ver < clamp_min)
3072c33676SMaxim Ag 		*min_ver = clamp_min;
3172c33676SMaxim Ag 	if (*max_ver > clamp_max)
3272c33676SMaxim Ag 		*max_ver = clamp_max;
3372c33676SMaxim Ag 
3472c33676SMaxim Ag 	return 1;
3572c33676SMaxim Ag }
3672c33676SMaxim Ag 
3772c33676SMaxim Ag int
3872c33676SMaxim Ag ssl_version_set_min(const SSL_METHOD *meth, uint16_t ver, uint16_t max_ver,
3972c33676SMaxim Ag     uint16_t *out_ver)
4072c33676SMaxim Ag {
4172c33676SMaxim Ag 	uint16_t min_version, max_version;
4272c33676SMaxim Ag 
4372c33676SMaxim Ag 	if (ver == 0) {
4472c33676SMaxim Ag 		*out_ver = meth->internal->min_version;
4572c33676SMaxim Ag 		return 1;
4672c33676SMaxim Ag 	}
4772c33676SMaxim Ag 
4872c33676SMaxim Ag 	min_version = ver;
4972c33676SMaxim Ag 	max_version = max_ver;
5072c33676SMaxim Ag 
5172c33676SMaxim Ag 	if (!ssl_clamp_version_range(&min_version, &max_version,
5272c33676SMaxim Ag 	    meth->internal->min_version, meth->internal->max_version))
5372c33676SMaxim Ag 		return 0;
5472c33676SMaxim Ag 
5572c33676SMaxim Ag 	*out_ver = min_version;
5672c33676SMaxim Ag 
5772c33676SMaxim Ag 	return 1;
5872c33676SMaxim Ag }
5972c33676SMaxim Ag 
6072c33676SMaxim Ag int
6172c33676SMaxim Ag ssl_version_set_max(const SSL_METHOD *meth, uint16_t ver, uint16_t min_ver,
6272c33676SMaxim Ag     uint16_t *out_ver)
6372c33676SMaxim Ag {
6472c33676SMaxim Ag 	uint16_t min_version, max_version;
6572c33676SMaxim Ag 
6672c33676SMaxim Ag 	if (ver == 0) {
6772c33676SMaxim Ag 		*out_ver = meth->internal->max_version;
6872c33676SMaxim Ag 		return 1;
6972c33676SMaxim Ag 	}
7072c33676SMaxim Ag 
7172c33676SMaxim Ag 	min_version = min_ver;
7272c33676SMaxim Ag 	max_version = ver;
7372c33676SMaxim Ag 
7472c33676SMaxim Ag 	if (!ssl_clamp_version_range(&min_version, &max_version,
7572c33676SMaxim Ag 	    meth->internal->min_version, meth->internal->max_version))
7672c33676SMaxim Ag 		return 0;
7772c33676SMaxim Ag 
7872c33676SMaxim Ag 	*out_ver = max_version;
7972c33676SMaxim Ag 
8072c33676SMaxim Ag 	return 1;
8172c33676SMaxim Ag }
8272c33676SMaxim Ag 
8372c33676SMaxim Ag int
8472c33676SMaxim Ag ssl_enabled_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver)
8572c33676SMaxim Ag {
8672c33676SMaxim Ag 	uint16_t min_version, max_version;
8772c33676SMaxim Ag 
8872c33676SMaxim Ag 	/*
8972c33676SMaxim Ag 	 * The enabled versions have to be a contiguous range, which means we
9072c33676SMaxim Ag 	 * cannot enable and disable single versions at our whim, even though
9172c33676SMaxim Ag 	 * this is what the OpenSSL flags allow. The historical way this has
9272c33676SMaxim Ag 	 * been handled is by making a flag mean that all higher versions
9372c33676SMaxim Ag 	 * are disabled, if any version lower than the flag is enabled.
9472c33676SMaxim Ag 	 */
9572c33676SMaxim Ag 
9672c33676SMaxim Ag 	min_version = 0;
9772c33676SMaxim Ag 	max_version = TLS1_3_VERSION;
9872c33676SMaxim Ag 
9972c33676SMaxim Ag 	if ((s->internal->options & SSL_OP_NO_TLSv1) == 0)
10072c33676SMaxim Ag 		min_version = TLS1_VERSION;
10172c33676SMaxim Ag 	else if ((s->internal->options & SSL_OP_NO_TLSv1_1) == 0)
10272c33676SMaxim Ag 		min_version = TLS1_1_VERSION;
10372c33676SMaxim Ag 	else if ((s->internal->options & SSL_OP_NO_TLSv1_2) == 0)
10472c33676SMaxim Ag 		min_version = TLS1_2_VERSION;
10572c33676SMaxim Ag 	else if ((s->internal->options & SSL_OP_NO_TLSv1_3) == 0)
10672c33676SMaxim Ag 		min_version = TLS1_3_VERSION;
10772c33676SMaxim Ag 
10872c33676SMaxim Ag 	if ((s->internal->options & SSL_OP_NO_TLSv1_3) && min_version < TLS1_3_VERSION)
10972c33676SMaxim Ag 		max_version = TLS1_2_VERSION;
11072c33676SMaxim Ag 	if ((s->internal->options & SSL_OP_NO_TLSv1_2) && min_version < TLS1_2_VERSION)
11172c33676SMaxim Ag 		max_version = TLS1_1_VERSION;
11272c33676SMaxim Ag 	if ((s->internal->options & SSL_OP_NO_TLSv1_1) && min_version < TLS1_1_VERSION)
11372c33676SMaxim Ag 		max_version = TLS1_VERSION;
11472c33676SMaxim Ag 	if ((s->internal->options & SSL_OP_NO_TLSv1) && min_version < TLS1_VERSION)
11572c33676SMaxim Ag 		max_version = 0;
11672c33676SMaxim Ag 
11772c33676SMaxim Ag 	/* Everything has been disabled... */
11872c33676SMaxim Ag 	if (min_version == 0 || max_version == 0)
11972c33676SMaxim Ag 		return 0;
12072c33676SMaxim Ag 
12172c33676SMaxim Ag 	/* Limit to configured version range. */
12272c33676SMaxim Ag 	if (!ssl_clamp_version_range(&min_version, &max_version,
12372c33676SMaxim Ag 	    s->internal->min_version, s->internal->max_version))
12472c33676SMaxim Ag 		return 0;
12572c33676SMaxim Ag 
12672c33676SMaxim Ag 	if (min_ver != NULL)
12772c33676SMaxim Ag 		*min_ver = min_version;
12872c33676SMaxim Ag 	if (max_ver != NULL)
12972c33676SMaxim Ag 		*max_ver = max_version;
13072c33676SMaxim Ag 
13172c33676SMaxim Ag 	return 1;
13272c33676SMaxim Ag }
13372c33676SMaxim Ag 
13472c33676SMaxim Ag int
13572c33676SMaxim Ag ssl_supported_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver)
13672c33676SMaxim Ag {
13772c33676SMaxim Ag 	uint16_t min_version, max_version;
13872c33676SMaxim Ag 
13972c33676SMaxim Ag 	/* DTLS cannot currently be disabled... */
14072c33676SMaxim Ag 	if (SSL_IS_DTLS(s)) {
14172c33676SMaxim Ag 		min_version = max_version = DTLS1_VERSION;
14272c33676SMaxim Ag 		goto done;
14372c33676SMaxim Ag 	}
14472c33676SMaxim Ag 
14572c33676SMaxim Ag 	if (!ssl_enabled_version_range(s, &min_version, &max_version))
14672c33676SMaxim Ag 		return 0;
14772c33676SMaxim Ag 
14872c33676SMaxim Ag 	/* Limit to the versions supported by this method. */
14972c33676SMaxim Ag 	if (!ssl_clamp_version_range(&min_version, &max_version,
15072c33676SMaxim Ag 	    s->method->internal->min_version,
15172c33676SMaxim Ag 	    s->method->internal->max_version))
15272c33676SMaxim Ag 		return 0;
15372c33676SMaxim Ag 
15472c33676SMaxim Ag  done:
15572c33676SMaxim Ag 	if (min_ver != NULL)
15672c33676SMaxim Ag 		*min_ver = min_version;
15772c33676SMaxim Ag 	if (max_ver != NULL)
15872c33676SMaxim Ag 		*max_ver = max_version;
15972c33676SMaxim Ag 
16072c33676SMaxim Ag 	return 1;
16172c33676SMaxim Ag }
16272c33676SMaxim Ag 
16372c33676SMaxim Ag int
16472c33676SMaxim Ag ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver)
16572c33676SMaxim Ag {
16672c33676SMaxim Ag 	uint16_t min_version, max_version, shared_version;
16772c33676SMaxim Ag 
16872c33676SMaxim Ag 	*max_ver = 0;
16972c33676SMaxim Ag 
17072c33676SMaxim Ag 	if (SSL_IS_DTLS(s)) {
17172c33676SMaxim Ag 		if (peer_ver >= DTLS1_VERSION) {
17272c33676SMaxim Ag 			*max_ver = DTLS1_VERSION;
17372c33676SMaxim Ag 			return 1;
17472c33676SMaxim Ag 		}
17572c33676SMaxim Ag 		return 0;
17672c33676SMaxim Ag 	}
17772c33676SMaxim Ag 
17872c33676SMaxim Ag 	if (peer_ver >= TLS1_3_VERSION)
17972c33676SMaxim Ag 		shared_version = TLS1_3_VERSION;
18072c33676SMaxim Ag 	else if (peer_ver >= TLS1_2_VERSION)
18172c33676SMaxim Ag 		shared_version = TLS1_2_VERSION;
18272c33676SMaxim Ag 	else if (peer_ver >= TLS1_1_VERSION)
18372c33676SMaxim Ag 		shared_version = TLS1_1_VERSION;
18472c33676SMaxim Ag 	else if (peer_ver >= TLS1_VERSION)
18572c33676SMaxim Ag 		shared_version = TLS1_VERSION;
18672c33676SMaxim Ag 	else
18772c33676SMaxim Ag 		return 0;
18872c33676SMaxim Ag 
18972c33676SMaxim Ag 	if (!ssl_supported_version_range(s, &min_version, &max_version))
19072c33676SMaxim Ag 		return 0;
19172c33676SMaxim Ag 
19272c33676SMaxim Ag 	if (shared_version < min_version)
19372c33676SMaxim Ag 		return 0;
19472c33676SMaxim Ag 
19572c33676SMaxim Ag 	if (shared_version > max_version)
19672c33676SMaxim Ag 		shared_version = max_version;
19772c33676SMaxim Ag 
19872c33676SMaxim Ag 	*max_ver = shared_version;
19972c33676SMaxim Ag 
20072c33676SMaxim Ag 	return 1;
20172c33676SMaxim Ag }
20272c33676SMaxim Ag 
203*8edacedfSDaniel Fojt int
204*8edacedfSDaniel Fojt ssl_downgrade_max_version(SSL *s, uint16_t *max_ver)
20572c33676SMaxim Ag {
206*8edacedfSDaniel Fojt 	uint16_t min_version, max_version;
20772c33676SMaxim Ag 
208*8edacedfSDaniel Fojt 	/*
209*8edacedfSDaniel Fojt 	 * The downgrade maximum version is based on the versions that are
210*8edacedfSDaniel Fojt 	 * enabled, however we also have to then limit to the versions
211*8edacedfSDaniel Fojt 	 * supported by the method. The SSL method will be changed during
212*8edacedfSDaniel Fojt 	 * version negotiation and when switching from the new stack to
213*8edacedfSDaniel Fojt 	 * the legacy context, as such we want to use the method from the
214*8edacedfSDaniel Fojt 	 * context.
215*8edacedfSDaniel Fojt 	 */
216*8edacedfSDaniel Fojt 
217*8edacedfSDaniel Fojt 	if (SSL_IS_DTLS(s)) {
218*8edacedfSDaniel Fojt 		*max_ver = DTLS1_VERSION;
219*8edacedfSDaniel Fojt 		return 1;
220*8edacedfSDaniel Fojt 	}
22172c33676SMaxim Ag 
22272c33676SMaxim Ag 	if (!ssl_enabled_version_range(s, &min_version, &max_version))
22372c33676SMaxim Ag 		return 0;
22472c33676SMaxim Ag 
22572c33676SMaxim Ag 	if (!ssl_clamp_version_range(&min_version, &max_version,
22672c33676SMaxim Ag 	    s->ctx->method->internal->min_version,
22772c33676SMaxim Ag 	    s->ctx->method->internal->max_version))
22872c33676SMaxim Ag 		return 0;
22972c33676SMaxim Ag 
230*8edacedfSDaniel Fojt 	*max_ver = max_version;
231*8edacedfSDaniel Fojt 
232*8edacedfSDaniel Fojt 	return 1;
23372c33676SMaxim Ag }
234