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