ssl_versions.c revision 1.11
1/* $OpenBSD: ssl_versions.c,v 1.11 2021/02/20 09:43:29 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_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver) 167{ 168 uint16_t min_version, max_version, shared_version; 169 170 *max_ver = 0; 171 172 if (SSL_is_dtls(s)) { 173 if (peer_ver >= DTLS1_VERSION) { 174 *max_ver = DTLS1_VERSION; 175 return 1; 176 } 177 return 0; 178 } 179 180 if (peer_ver >= TLS1_3_VERSION) 181 shared_version = TLS1_3_VERSION; 182 else if (peer_ver >= TLS1_2_VERSION) 183 shared_version = TLS1_2_VERSION; 184 else if (peer_ver >= TLS1_1_VERSION) 185 shared_version = TLS1_1_VERSION; 186 else if (peer_ver >= TLS1_VERSION) 187 shared_version = TLS1_VERSION; 188 else 189 return 0; 190 191 if (!ssl_supported_version_range(s, &min_version, &max_version)) 192 return 0; 193 194 if (shared_version < min_version) 195 return 0; 196 197 if (shared_version > max_version) 198 shared_version = max_version; 199 200 *max_ver = shared_version; 201 202 return 1; 203} 204 205int 206ssl_downgrade_max_version(SSL *s, uint16_t *max_ver) 207{ 208 uint16_t min_version, max_version; 209 210 /* 211 * The downgrade maximum version is based on the versions that are 212 * enabled, however we also have to then limit to the versions 213 * supported by the method. The SSL method will be changed during 214 * version negotiation and when switching from the new stack to 215 * the legacy context, as such we want to use the method from the 216 * context. 217 */ 218 219 if (SSL_is_dtls(s)) { 220 *max_ver = DTLS1_VERSION; 221 return 1; 222 } 223 224 if (!ssl_enabled_version_range(s, &min_version, &max_version)) 225 return 0; 226 227 if (!ssl_clamp_version_range(&min_version, &max_version, 228 s->ctx->method->internal->min_version, 229 s->ctx->method->internal->max_version)) 230 return 0; 231 232 *max_ver = max_version; 233 234 return 1; 235} 236 237int 238ssl_legacy_stack_version(SSL *s, uint16_t version) 239{ 240 if (SSL_is_dtls(s)) 241 return version == DTLS1_VERSION || version == DTLS1_2_VERSION; 242 243 return version == TLS1_VERSION || version == TLS1_1_VERSION || 244 version == TLS1_2_VERSION; 245} 246