xref: /openbsd-src/lib/libssl/ssl_versions.c (revision d59bb9942320b767f2a19aaa7690c8c6e30b724c)
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 
19 static int
20 ssl_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 
36 int
37 ssl_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 
83 int
84 ssl_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 
112 int
113 ssl_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 
150 uint16_t
151 ssl_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