ssl_versions.c revision 1.1
1/*
2 * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "ssl_locl.h"
18
19static int
20ssl_clamp_version_range(uint16_t *min_ver, uint16_t *max_ver,
21    uint16_t clamp_min, uint16_t clamp_max)
22{
23	if (clamp_min > clamp_max || *min_ver > *max_ver)
24		return 0;
25	if (clamp_max < *min_ver || clamp_min > *max_ver)
26		return 0;
27
28	if (*min_ver < clamp_min)
29		*min_ver = clamp_min;
30	if (*max_ver > clamp_max)
31		*max_ver = clamp_max;
32
33	return 1;
34}
35
36int
37ssl_enabled_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver)
38{
39	uint16_t min_version, max_version;
40
41	/*
42	 * The enabled versions have to be a contiguous range, which means we
43	 * cannot enable and disable single versions at our whim, even though
44	 * this is what the OpenSSL flags allow. The historical way this has
45	 * been handled is by making a flag mean that all higher versions
46	 * are disabled, if any version lower than the flag is enabled.
47	 */
48
49	min_version = 0;
50	max_version = TLS1_2_VERSION;
51
52	if ((s->internal->options & SSL_OP_NO_TLSv1) == 0)
53		min_version = TLS1_VERSION;
54	else if ((s->internal->options & SSL_OP_NO_TLSv1_1) == 0)
55		min_version = TLS1_1_VERSION;
56	else if ((s->internal->options & SSL_OP_NO_TLSv1_2) == 0)
57		min_version = TLS1_2_VERSION;
58
59	if ((s->internal->options & SSL_OP_NO_TLSv1_2) && min_version < TLS1_2_VERSION)
60		max_version = TLS1_1_VERSION;
61	if ((s->internal->options & SSL_OP_NO_TLSv1_1) && min_version < TLS1_1_VERSION)
62		max_version = TLS1_VERSION;
63	if ((s->internal->options & SSL_OP_NO_TLSv1) && min_version < TLS1_VERSION)
64		max_version = 0;
65
66	/* Everything has been disabled... */
67	if (min_version == 0 || max_version == 0)
68		return 0;
69
70	/* Limit to configured version range. */
71	if (!ssl_clamp_version_range(&min_version, &max_version,
72	    s->internal->min_version, s->internal->max_version))
73		return 0;
74
75	if (min_ver != NULL)
76		*min_ver = min_version;
77	if (max_ver != NULL)
78		*max_ver = max_version;
79
80	return 1;
81}
82
83int
84ssl_supported_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver)
85{
86	uint16_t min_version, max_version;
87
88	/* DTLS cannot currently be disabled... */
89	if (SSL_IS_DTLS(s)) {
90		min_version = max_version = DTLS1_VERSION;
91		goto done;
92	}
93
94	if (!ssl_enabled_version_range(s, &min_version, &max_version))
95		return 0;
96
97	/* Limit to the versions supported by this method. */
98	if (!ssl_clamp_version_range(&min_version, &max_version,
99	    s->method->internal->min_version,
100	    s->method->internal->max_version))
101		return 0;
102
103 done:
104	if (min_ver != NULL)
105		*min_ver = min_version;
106	if (max_ver != NULL)
107		*max_ver = max_version;
108
109	return 1;
110}
111
112int
113ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver)
114{
115	uint16_t min_version, max_version, shared_version;
116
117	*max_ver = 0;
118
119	if (SSL_IS_DTLS(s)) {
120		if (peer_ver >= DTLS1_VERSION) {
121			*max_ver = DTLS1_VERSION;
122			return 1;
123		}
124		return 0;
125	}
126
127	if (peer_ver >= TLS1_2_VERSION)
128		shared_version = TLS1_2_VERSION;
129	else if (peer_ver >= TLS1_1_VERSION)
130		shared_version = TLS1_1_VERSION;
131	else if (peer_ver >= TLS1_VERSION)
132		shared_version = TLS1_VERSION;
133	else
134		return 0;
135
136	if (!ssl_supported_version_range(s, &min_version, &max_version))
137		return 0;
138
139	if (shared_version < min_version)
140		return 0;
141
142	if (shared_version > max_version)
143		shared_version = max_version;
144
145	*max_ver = shared_version;
146
147	return 1;
148}
149
150uint16_t
151ssl_max_server_version(SSL *s)
152{
153	uint16_t max_version, min_version = 0;
154
155	if (SSL_IS_DTLS(s))
156		return (DTLS1_VERSION);
157
158	if (!ssl_enabled_version_range(s, &min_version, &max_version))
159		return 0;
160
161	/*
162	 * Limit to the versions supported by this method. The SSL method
163	 * will be changed during version negotiation, as such we want to
164	 * use the SSL method from the context.
165	 */
166	if (!ssl_clamp_version_range(&min_version, &max_version,
167	    s->ctx->method->internal->min_version,
168	    s->ctx->method->internal->max_version))
169		return 0;
170
171	return (max_version);
172}
173