1 /* 2 * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.ssl; 27 28 import java.security.CryptoPrimitive; 29 import java.util.ArrayList; 30 import java.util.Collections; 31 import java.util.EnumSet; 32 import java.util.List; 33 34 /** 35 * Enum for an SSL/TLS/DTLS protocol version. 36 * 37 * @author Andreas Sterbenz 38 * @since 1.4.1 39 */ 40 enum ProtocolVersion { 41 TLS13 (0x0304, "TLSv1.3", false), 42 TLS12 (0x0303, "TLSv1.2", false), 43 TLS11 (0x0302, "TLSv1.1", false), 44 TLS10 (0x0301, "TLSv1", false), 45 SSL30 (0x0300, "SSLv3", false), 46 SSL20Hello (0x0002, "SSLv2Hello", false), 47 48 DTLS12 (0xFEFD, "DTLSv1.2", true), 49 DTLS10 (0xFEFF, "DTLSv1.0", true), 50 51 // Dummy protocol version value for invalid SSLSession 52 NONE (-1, "NONE", false); 53 54 55 final int id; 56 final String name; 57 final boolean isDTLS; 58 final byte major; 59 final byte minor; 60 final boolean isAvailable; 61 62 // The limit of maximum protocol version 63 static final int LIMIT_MAX_VALUE = 0xFFFF; 64 65 // The limit of minimum protocol version 66 static final int LIMIT_MIN_VALUE = 0x0000; 67 68 // (D)TLS ProtocolVersion array for TLS 1.0 and previous versions. 69 static final ProtocolVersion[] PROTOCOLS_TO_10 = new ProtocolVersion[] { 70 TLS10, SSL30 71 }; 72 73 // (D)TLS ProtocolVersion array for TLS 1.1/DTLS 1.0 and previous versions. 74 static final ProtocolVersion[] PROTOCOLS_TO_11 = new ProtocolVersion[] { 75 TLS11, TLS10, SSL30, DTLS10 76 }; 77 78 // (D)TLS ProtocolVersion array for (D)TLS 1.2 and previous versions. 79 static final ProtocolVersion[] PROTOCOLS_TO_12 = new ProtocolVersion[] { 80 TLS12, TLS11, TLS10, SSL30, DTLS12, DTLS10 81 }; 82 83 // (D)TLS ProtocolVersion array for (D)TLS 1.3 and previous versions. 84 static final ProtocolVersion[] PROTOCOLS_TO_13 = new ProtocolVersion[] { 85 TLS13, TLS12, TLS11, TLS10, SSL30, DTLS12, DTLS10 86 }; 87 88 // No protocol version specified. 89 static final ProtocolVersion[] PROTOCOLS_OF_NONE = new ProtocolVersion[] { 90 NONE 91 }; 92 93 // (D)TLS ProtocolVersion array for SSL 3.0. 94 static final ProtocolVersion[] PROTOCOLS_OF_30 = new ProtocolVersion[] { 95 SSL30 96 }; 97 98 // (D)TLS ProtocolVersion array for TLS 1.1/DTSL 1.0. 99 static final ProtocolVersion[] PROTOCOLS_OF_11 = new ProtocolVersion[] { 100 TLS11, DTLS10 101 }; 102 103 // (D)TLS ProtocolVersion array for (D)TLS 1.2. 104 static final ProtocolVersion[] PROTOCOLS_OF_12 = new ProtocolVersion[] { 105 TLS12, DTLS12 106 }; 107 108 // (D)TLS ProtocolVersion array for (D)TLS 1.3. 109 static final ProtocolVersion[] PROTOCOLS_OF_13 = new ProtocolVersion[] { 110 TLS13 111 }; 112 113 // (D)TLS ProtocolVersion array for TSL 1.0/1.1 and DTLS 1.0. 114 static final ProtocolVersion[] PROTOCOLS_10_11 = new ProtocolVersion[] { 115 TLS11, TLS10, DTLS10 116 }; 117 118 // (D)TLS ProtocolVersion array for TSL 1.1/1.2 and DTLS 1.0/1.2. 119 static final ProtocolVersion[] PROTOCOLS_11_12 = new ProtocolVersion[] { 120 TLS12, TLS11, DTLS12, DTLS10 121 }; 122 123 // (D)TLS ProtocolVersion array for TSL 1.2/1.3 and DTLS 1.2/1.3. 124 static final ProtocolVersion[] PROTOCOLS_12_13 = new ProtocolVersion[] { 125 TLS13, TLS12, DTLS12 126 }; 127 128 // (D)TLS ProtocolVersion array for TSL 1.0/1.1/1.2 and DTLS 1.0/1.2. 129 static final ProtocolVersion[] PROTOCOLS_10_12 = new ProtocolVersion[] { 130 TLS12, TLS11, TLS10, DTLS12, DTLS10 131 }; 132 133 // TLS ProtocolVersion array for TLS 1.2 and previous versions. 134 static final ProtocolVersion[] PROTOCOLS_TO_TLS12 = new ProtocolVersion[] { 135 TLS12, TLS11, TLS10, SSL30 136 }; 137 138 // TLS ProtocolVersion array for TLS 1.1 and previous versions. 139 static final ProtocolVersion[] PROTOCOLS_TO_TLS11 = new ProtocolVersion[] { 140 TLS11, TLS10, SSL30 141 }; 142 143 // TLS ProtocolVersion array for TLS 1.0 and previous versions. 144 static final ProtocolVersion[] PROTOCOLS_TO_TLS10 = new ProtocolVersion[] { 145 TLS10, SSL30 146 }; 147 148 // Empty ProtocolVersion array 149 static final ProtocolVersion[] PROTOCOLS_EMPTY = new ProtocolVersion[0]; 150 ProtocolVersion(int id, String name, boolean isDTLS)151 private ProtocolVersion(int id, String name, boolean isDTLS) { 152 this.id = id; 153 this.name = name; 154 this.isDTLS = isDTLS; 155 this.major = (byte)((id >>> 8) & 0xFF); 156 this.minor = (byte)(id & 0xFF); 157 158 this.isAvailable = SSLAlgorithmConstraints.DEFAULT_SSL_ONLY.permits( 159 EnumSet.<CryptoPrimitive>of(CryptoPrimitive.KEY_AGREEMENT), 160 name, null); 161 } 162 163 /** 164 * Return a ProtocolVersion with the specified major and minor 165 * version numbers. 166 */ valueOf(byte major, byte minor)167 static ProtocolVersion valueOf(byte major, byte minor) { 168 for (ProtocolVersion pv : ProtocolVersion.values()) { 169 if ((pv.major == major) && (pv.minor == minor)) { 170 return pv; 171 } 172 } 173 174 return null; 175 } 176 177 /** 178 * Return a ProtocolVersion with the specified version number. 179 */ valueOf(int id)180 static ProtocolVersion valueOf(int id) { 181 for (ProtocolVersion pv : ProtocolVersion.values()) { 182 if (pv.id == id) { 183 return pv; 184 } 185 } 186 187 return null; 188 } 189 190 /** 191 * Return name of a (D)TLS protocol specified by major and 192 * minor version numbers. 193 */ nameOf(byte major, byte minor)194 static String nameOf(byte major, byte minor) { 195 for (ProtocolVersion pv : ProtocolVersion.values()) { 196 if ((pv.major == major) && (pv.minor == minor)) { 197 return pv.name; 198 } 199 } 200 201 return "(D)TLS-" + major + "." + minor; 202 } 203 204 /** 205 * Return name of a (D)TLS protocol specified by a protocol number. 206 */ nameOf(int id)207 static String nameOf(int id) { 208 return nameOf((byte)((id >>> 8) & 0xFF), (byte)(id & 0xFF)); 209 } 210 211 /** 212 * Return a ProtocolVersion for the given (D)TLS protocol name. 213 */ nameOf(String name)214 static ProtocolVersion nameOf(String name) { 215 for (ProtocolVersion pv : ProtocolVersion.values()) { 216 if (pv.name.equals(name)) { 217 return pv; 218 } 219 } 220 221 return null; 222 } 223 224 /** 225 * Return true if the specific (D)TLS protocol is negotiable. 226 * 227 * Used to filter out SSLv2Hello and protocol numbers less than the 228 * minimal supported protocol versions. 229 */ isNegotiable( byte major, byte minor, boolean isDTLS, boolean allowSSL20Hello)230 static boolean isNegotiable( 231 byte major, byte minor, boolean isDTLS, boolean allowSSL20Hello) { 232 int v = ((major & 0xFF) << 8) | (minor & 0xFF); 233 if (isDTLS) { 234 return v <= DTLS10.id; 235 } else { 236 if (v < SSL30.id) { 237 if (!allowSSL20Hello || (v != SSL20Hello.id)) { 238 return false; 239 } 240 } 241 return true; 242 } 243 } 244 245 /** 246 * Get names of a list of ProtocolVersion objects. 247 */ toStringArray(List<ProtocolVersion> protocolVersions)248 static String[] toStringArray(List<ProtocolVersion> protocolVersions) { 249 if ((protocolVersions != null) && !protocolVersions.isEmpty()) { 250 String[] protocolNames = new String[protocolVersions.size()]; 251 int i = 0; 252 for (ProtocolVersion pv : protocolVersions) { 253 protocolNames[i++] = pv.name; 254 } 255 256 return protocolNames; 257 } 258 259 return new String[0]; 260 } 261 262 /** 263 * Get names of a list of protocol version identifiers. 264 */ toStringArray(int[] protocolVersions)265 static String[] toStringArray(int[] protocolVersions) { 266 if ((protocolVersions != null) && protocolVersions.length != 0) { 267 String[] protocolNames = new String[protocolVersions.length]; 268 int i = 0; 269 for (int pv : protocolVersions) { 270 protocolNames[i++] = ProtocolVersion.nameOf(pv); 271 } 272 273 return protocolNames; 274 } 275 276 return new String[0]; 277 } 278 279 /** 280 * Get a list of ProtocolVersion objects of an array protocol 281 * version names. 282 */ namesOf(String[] protocolNames)283 static List<ProtocolVersion> namesOf(String[] protocolNames) { 284 if (protocolNames == null || protocolNames.length == 0) { 285 return Collections.<ProtocolVersion>emptyList(); 286 } 287 288 List<ProtocolVersion> pvs = new ArrayList<>(protocolNames.length); 289 for (String pn : protocolNames) { 290 ProtocolVersion pv = ProtocolVersion.nameOf(pn); 291 if (pv == null) { 292 throw new IllegalArgumentException( 293 "Unsupported protocol" + pn); 294 } 295 296 pvs.add(pv); 297 } 298 299 return Collections.unmodifiableList(pvs); 300 } 301 302 /** 303 * Return true if the specific protocol version name is 304 * of (D)TLS 1.2 or newer version. 305 */ useTLS12PlusSpec(String name)306 static boolean useTLS12PlusSpec(String name) { 307 ProtocolVersion pv = ProtocolVersion.nameOf(name); 308 if (pv != null && pv != NONE) { 309 return pv.isDTLS ? (pv.id <= DTLS12.id) : (pv.id >= TLS12.id); 310 } 311 312 return false; 313 } 314 315 /** 316 * Compares this object with the specified ProtocolVersion. 317 * 318 * @see java.lang.Comparable 319 */ compare(ProtocolVersion that)320 int compare(ProtocolVersion that) { 321 if (this == that) { 322 return 0; 323 } 324 325 if (this == ProtocolVersion.NONE) { 326 return -1; 327 } else if (that == ProtocolVersion.NONE) { 328 return 1; 329 } 330 331 if (isDTLS) { 332 return that.id - this.id; 333 } else { 334 return this.id - that.id; 335 } 336 } 337 338 /** 339 * Return true if this ProtocolVersion object is of (D)TLS 1.3 or 340 * newer version. 341 */ useTLS13PlusSpec()342 boolean useTLS13PlusSpec() { 343 return isDTLS ? (this.id < DTLS12.id) : (this.id >= TLS13.id); 344 } 345 346 /** 347 * Return true if this ProtocolVersion object is of (D)TLS 1.2 or 348 * newer version. 349 */ useTLS12PlusSpec()350 boolean useTLS12PlusSpec() { 351 return isDTLS ? (this.id <= DTLS12.id) : (this.id >= TLS12.id); 352 } 353 354 /** 355 * Return true if this ProtocolVersion object is of 356 * TLS 1.1/DTLS 1.0 or newer version. 357 */ useTLS11PlusSpec()358 boolean useTLS11PlusSpec() { 359 return isDTLS ? true : (this.id >= TLS11.id); 360 } 361 362 /** 363 * Return true if this ProtocolVersion object is of TLS 1.0 or 364 * newer version. 365 */ useTLS10PlusSpec()366 boolean useTLS10PlusSpec() { 367 return isDTLS ? true : (this.id >= TLS10.id); 368 } 369 370 /** 371 * Return true if this ProtocolVersion object is of TLS 1.0 or 372 * newer version. 373 */ useTLS10PlusSpec(int id, boolean isDTLS)374 static boolean useTLS10PlusSpec(int id, boolean isDTLS) { 375 return isDTLS ? true : (id >= TLS10.id); 376 } 377 378 /** 379 * Return true if this ProtocolVersion object is of (D)TLS 1.3 or 380 * newer version. 381 */ useTLS13PlusSpec(int id, boolean isDTLS)382 static boolean useTLS13PlusSpec(int id, boolean isDTLS) { 383 return isDTLS ? (id < DTLS12.id) : (id >= TLS13.id); 384 } 385 386 /** 387 * Select the lower of that suggested protocol version and 388 * the highest of the listed protocol versions. 389 * 390 * @param listedVersions the listed protocol version 391 * @param suggestedVersion the suggested protocol version 392 */ selectedFrom( List<ProtocolVersion> listedVersions, int suggestedVersion)393 static ProtocolVersion selectedFrom( 394 List<ProtocolVersion> listedVersions, int suggestedVersion) { 395 ProtocolVersion selectedVersion = ProtocolVersion.NONE; 396 for (ProtocolVersion pv : listedVersions) { 397 if (pv.id == suggestedVersion) { 398 return pv; 399 } else if (pv.isDTLS) { 400 if (pv.id > suggestedVersion && pv.id < selectedVersion.id) { 401 selectedVersion = pv; 402 } 403 } else { 404 if (pv.id < suggestedVersion && pv.id > selectedVersion.id) { 405 selectedVersion = pv; 406 } 407 } 408 } 409 410 return selectedVersion; 411 } 412 } 413