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