ssl_versions.c revision 1.14
1/* $OpenBSD: ssl_versions.c,v 1.14 2021/03/10 18:27:02 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
20static int
21ssl_clamp_tls_version_range(uint16_t *min_ver, uint16_t *max_ver,
22    uint16_t clamp_min, uint16_t clamp_max)
23{
24	if (clamp_min > clamp_max || *min_ver > *max_ver)
25		return 0;
26	if (clamp_max < *min_ver || clamp_min > *max_ver)
27		return 0;
28
29	if (*min_ver < clamp_min)
30		*min_ver = clamp_min;
31	if (*max_ver > clamp_max)
32		*max_ver = clamp_max;
33
34	return 1;
35}
36
37int
38ssl_version_set_min(const SSL_METHOD *meth, uint16_t proto_ver,
39    uint16_t max_tls_ver, uint16_t *out_tls_ver, uint16_t *out_proto_ver)
40{
41	uint16_t min_version, max_version;
42
43	if (proto_ver == 0) {
44		*out_tls_ver = meth->internal->min_tls_version;
45		*out_proto_ver = 0;
46		return 1;
47	}
48	if (meth->internal->dtls) {
49		if (proto_ver != DTLS1_VERSION)
50			return 0;
51		*out_tls_ver = TLS1_1_VERSION;
52		*out_proto_ver = proto_ver;
53		return 1;
54	}
55
56	min_version = proto_ver;
57	max_version = max_tls_ver;
58
59	if (!ssl_clamp_tls_version_range(&min_version, &max_version,
60	    meth->internal->min_tls_version, meth->internal->max_tls_version))
61		return 0;
62
63	*out_tls_ver = min_version;
64	*out_proto_ver = min_version;
65
66	return 1;
67}
68
69int
70ssl_version_set_max(const SSL_METHOD *meth, uint16_t proto_ver,
71    uint16_t min_tls_ver, uint16_t *out_tls_ver, uint16_t *out_proto_ver)
72{
73	uint16_t min_version, max_version;
74
75	if (proto_ver == 0) {
76		*out_tls_ver = meth->internal->max_tls_version;
77		*out_proto_ver = 0;
78		return 1;
79	}
80	if (meth->internal->dtls) {
81		if (proto_ver != DTLS1_VERSION)
82			return 0;
83		*out_tls_ver = TLS1_1_VERSION;
84		*out_proto_ver = proto_ver;
85		return 1;
86	}
87
88	min_version = min_tls_ver;
89	max_version = proto_ver;
90
91	if (!ssl_clamp_tls_version_range(&min_version, &max_version,
92	    meth->internal->min_tls_version, meth->internal->max_tls_version))
93		return 0;
94
95	*out_tls_ver = max_version;
96	*out_proto_ver = max_version;
97
98	return 1;
99}
100
101int
102ssl_enabled_tls_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver)
103{
104	uint16_t min_version, max_version;
105
106	/*
107	 * The enabled versions have to be a contiguous range, which means we
108	 * cannot enable and disable single versions at our whim, even though
109	 * this is what the OpenSSL flags allow. The historical way this has
110	 * been handled is by making a flag mean that all higher versions
111	 * are disabled, if any version lower than the flag is enabled.
112	 */
113
114	min_version = 0;
115	max_version = TLS1_3_VERSION;
116
117	if ((s->internal->options & SSL_OP_NO_TLSv1) == 0)
118		min_version = TLS1_VERSION;
119	else if ((s->internal->options & SSL_OP_NO_TLSv1_1) == 0)
120		min_version = TLS1_1_VERSION;
121	else if ((s->internal->options & SSL_OP_NO_TLSv1_2) == 0)
122		min_version = TLS1_2_VERSION;
123	else if ((s->internal->options & SSL_OP_NO_TLSv1_3) == 0)
124		min_version = TLS1_3_VERSION;
125
126	if ((s->internal->options & SSL_OP_NO_TLSv1_3) && min_version < TLS1_3_VERSION)
127		max_version = TLS1_2_VERSION;
128	if ((s->internal->options & SSL_OP_NO_TLSv1_2) && min_version < TLS1_2_VERSION)
129		max_version = TLS1_1_VERSION;
130	if ((s->internal->options & SSL_OP_NO_TLSv1_1) && min_version < TLS1_1_VERSION)
131		max_version = TLS1_VERSION;
132	if ((s->internal->options & SSL_OP_NO_TLSv1) && min_version < TLS1_VERSION)
133		max_version = 0;
134
135	/* Everything has been disabled... */
136	if (min_version == 0 || max_version == 0)
137		return 0;
138
139	/* Limit to configured version range. */
140	if (!ssl_clamp_tls_version_range(&min_version, &max_version,
141	    s->internal->min_tls_version, s->internal->max_tls_version))
142		return 0;
143
144	if (min_ver != NULL)
145		*min_ver = min_version;
146	if (max_ver != NULL)
147		*max_ver = max_version;
148
149	return 1;
150}
151
152int
153ssl_supported_tls_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver)
154{
155	uint16_t min_version, max_version;
156
157	if (!ssl_enabled_tls_version_range(s, &min_version, &max_version))
158		return 0;
159
160	/* Limit to the versions supported by this method. */
161	if (!ssl_clamp_tls_version_range(&min_version, &max_version,
162	    s->method->internal->min_tls_version,
163	    s->method->internal->max_tls_version))
164		return 0;
165
166	if (min_ver != NULL)
167		*min_ver = min_version;
168	if (max_ver != NULL)
169		*max_ver = max_version;
170
171	return 1;
172}
173
174uint16_t
175ssl_tls_version(uint16_t version)
176{
177	if (version == TLS1_VERSION || version == TLS1_1_VERSION ||
178	    version == TLS1_2_VERSION || version == TLS1_3_VERSION)
179		return version;
180
181	if (version == DTLS1_VERSION)
182		return TLS1_1_VERSION;
183	if (version == DTLS1_2_VERSION)
184		return TLS1_2_VERSION;
185
186	return 0;
187}
188
189uint16_t
190ssl_effective_tls_version(SSL *s)
191{
192	if (S3I(s)->hs.negotiated_tls_version > 0)
193		return S3I(s)->hs.negotiated_tls_version;
194
195	return S3I(s)->hs.our_max_tls_version;
196}
197
198int
199ssl_max_supported_version(SSL *s, uint16_t *max_ver)
200{
201	*max_ver = 0;
202
203	if (SSL_is_dtls(s)) {
204		*max_ver = DTLS1_VERSION;
205		return 1;
206	}
207
208	if (!ssl_supported_tls_version_range(s, NULL, max_ver))
209		return 0;
210
211	return 1;
212}
213
214int
215ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver)
216{
217	uint16_t min_version, max_version, shared_version;
218
219	*max_ver = 0;
220
221	if (SSL_is_dtls(s)) {
222		if (peer_ver >= DTLS1_VERSION) {
223			*max_ver = DTLS1_VERSION;
224			return 1;
225		}
226		return 0;
227	}
228
229	if (peer_ver >= TLS1_3_VERSION)
230		shared_version = TLS1_3_VERSION;
231	else if (peer_ver >= TLS1_2_VERSION)
232		shared_version = TLS1_2_VERSION;
233	else if (peer_ver >= TLS1_1_VERSION)
234		shared_version = TLS1_1_VERSION;
235	else if (peer_ver >= TLS1_VERSION)
236		shared_version = TLS1_VERSION;
237	else
238		return 0;
239
240	if (!ssl_supported_tls_version_range(s, &min_version, &max_version))
241		return 0;
242
243	if (shared_version < min_version)
244		return 0;
245
246	if (shared_version > max_version)
247		shared_version = max_version;
248
249	*max_ver = shared_version;
250
251	return 1;
252}
253
254int
255ssl_downgrade_max_version(SSL *s, uint16_t *max_ver)
256{
257	uint16_t min_version, max_version;
258
259	/*
260	 * The downgrade maximum version is based on the versions that are
261	 * enabled, however we also have to then limit to the versions
262	 * supported by the method. The SSL method will be changed during
263	 * version negotiation and when switching from the new stack to
264	 * the legacy context, as such we want to use the method from the
265	 * context.
266	 */
267
268	if (SSL_is_dtls(s)) {
269		*max_ver = DTLS1_VERSION;
270		return 1;
271	}
272
273	if (!ssl_enabled_tls_version_range(s, &min_version, &max_version))
274		return 0;
275
276	if (!ssl_clamp_tls_version_range(&min_version, &max_version,
277	    s->ctx->method->internal->min_tls_version,
278	    s->ctx->method->internal->max_tls_version))
279		return 0;
280
281	*max_ver = max_version;
282
283	return 1;
284}
285
286int
287ssl_check_version_from_server(SSL *s, uint16_t server_version)
288{
289	uint16_t min_version, max_version;
290
291	/* Ensure that the version selected by the server is valid. */
292
293	if (SSL_is_dtls(s))
294		return (server_version == DTLS1_VERSION);
295
296	if (!ssl_supported_tls_version_range(s, &min_version, &max_version))
297		return 0;
298
299	return (server_version >= min_version && server_version <= max_version);
300}
301
302int
303ssl_legacy_stack_version(SSL *s, uint16_t version)
304{
305	if (SSL_is_dtls(s))
306		return version == DTLS1_VERSION || version == DTLS1_2_VERSION;
307
308	return version == TLS1_VERSION || version == TLS1_1_VERSION ||
309	    version == TLS1_2_VERSION;
310}
311