ssl_versions.c revision 1.2
1/* $OpenBSD: ssl_versions.c,v 1.2 2017/05/06 16:18:36 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_enabled_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver) 39{ 40 uint16_t min_version, max_version; 41 42 /* 43 * The enabled versions have to be a contiguous range, which means we 44 * cannot enable and disable single versions at our whim, even though 45 * this is what the OpenSSL flags allow. The historical way this has 46 * been handled is by making a flag mean that all higher versions 47 * are disabled, if any version lower than the flag is enabled. 48 */ 49 50 min_version = 0; 51 max_version = TLS1_2_VERSION; 52 53 if ((s->internal->options & SSL_OP_NO_TLSv1) == 0) 54 min_version = TLS1_VERSION; 55 else if ((s->internal->options & SSL_OP_NO_TLSv1_1) == 0) 56 min_version = TLS1_1_VERSION; 57 else if ((s->internal->options & SSL_OP_NO_TLSv1_2) == 0) 58 min_version = TLS1_2_VERSION; 59 60 if ((s->internal->options & SSL_OP_NO_TLSv1_2) && min_version < TLS1_2_VERSION) 61 max_version = TLS1_1_VERSION; 62 if ((s->internal->options & SSL_OP_NO_TLSv1_1) && min_version < TLS1_1_VERSION) 63 max_version = TLS1_VERSION; 64 if ((s->internal->options & SSL_OP_NO_TLSv1) && min_version < TLS1_VERSION) 65 max_version = 0; 66 67 /* Everything has been disabled... */ 68 if (min_version == 0 || max_version == 0) 69 return 0; 70 71 /* Limit to configured version range. */ 72 if (!ssl_clamp_version_range(&min_version, &max_version, 73 s->internal->min_version, s->internal->max_version)) 74 return 0; 75 76 if (min_ver != NULL) 77 *min_ver = min_version; 78 if (max_ver != NULL) 79 *max_ver = max_version; 80 81 return 1; 82} 83 84int 85ssl_supported_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver) 86{ 87 uint16_t min_version, max_version; 88 89 /* DTLS cannot currently be disabled... */ 90 if (SSL_IS_DTLS(s)) { 91 min_version = max_version = DTLS1_VERSION; 92 goto done; 93 } 94 95 if (!ssl_enabled_version_range(s, &min_version, &max_version)) 96 return 0; 97 98 /* Limit to the versions supported by this method. */ 99 if (!ssl_clamp_version_range(&min_version, &max_version, 100 s->method->internal->min_version, 101 s->method->internal->max_version)) 102 return 0; 103 104 done: 105 if (min_ver != NULL) 106 *min_ver = min_version; 107 if (max_ver != NULL) 108 *max_ver = max_version; 109 110 return 1; 111} 112 113int 114ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver) 115{ 116 uint16_t min_version, max_version, shared_version; 117 118 *max_ver = 0; 119 120 if (SSL_IS_DTLS(s)) { 121 if (peer_ver >= DTLS1_VERSION) { 122 *max_ver = DTLS1_VERSION; 123 return 1; 124 } 125 return 0; 126 } 127 128 if (peer_ver >= TLS1_2_VERSION) 129 shared_version = TLS1_2_VERSION; 130 else if (peer_ver >= TLS1_1_VERSION) 131 shared_version = TLS1_1_VERSION; 132 else if (peer_ver >= TLS1_VERSION) 133 shared_version = TLS1_VERSION; 134 else 135 return 0; 136 137 if (!ssl_supported_version_range(s, &min_version, &max_version)) 138 return 0; 139 140 if (shared_version < min_version) 141 return 0; 142 143 if (shared_version > max_version) 144 shared_version = max_version; 145 146 *max_ver = shared_version; 147 148 return 1; 149} 150 151uint16_t 152ssl_max_server_version(SSL *s) 153{ 154 uint16_t max_version, min_version = 0; 155 156 if (SSL_IS_DTLS(s)) 157 return (DTLS1_VERSION); 158 159 if (!ssl_enabled_version_range(s, &min_version, &max_version)) 160 return 0; 161 162 /* 163 * Limit to the versions supported by this method. The SSL method 164 * will be changed during version negotiation, as such we want to 165 * use the SSL method from the context. 166 */ 167 if (!ssl_clamp_version_range(&min_version, &max_version, 168 s->ctx->method->internal->min_version, 169 s->ctx->method->internal->max_version)) 170 return 0; 171 172 return (max_version); 173} 174