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