1 /* |
1 /* |
2 * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
25 |
25 |
26 package sun.security.ssl; |
26 package sun.security.ssl; |
27 |
27 |
28 import java.util.*; |
28 import java.util.*; |
29 import java.security.CryptoPrimitive; |
29 import java.security.CryptoPrimitive; |
|
30 import sun.security.ssl.CipherSuite.*; |
30 |
31 |
31 /** |
32 /** |
32 * Type safe enum for an SSL/TLS protocol version. Instances are obtained |
33 * Type safe enum for an SSL/TLS protocol version. Instances are obtained |
33 * using the static factory methods or by referencing the static members |
34 * using the static factory methods or by referencing the static members |
34 * in this class. Member variables are final and can be accessed without |
35 * in this class. Member variables are final and can be accessed without |
59 final static int LIMIT_MIN_VALUE = 0x0000; |
60 final static int LIMIT_MIN_VALUE = 0x0000; |
60 |
61 |
61 // Dummy protocol version value for invalid SSLSession |
62 // Dummy protocol version value for invalid SSLSession |
62 final static ProtocolVersion NONE = new ProtocolVersion(-1, "NONE"); |
63 final static ProtocolVersion NONE = new ProtocolVersion(-1, "NONE"); |
63 |
64 |
64 // If enabled, send/ accept SSLv2 hello messages |
65 // If enabled, send/accept SSLv2 hello messages |
65 final static ProtocolVersion SSL20Hello = new ProtocolVersion(0x0002, |
66 final static ProtocolVersion SSL20Hello = |
66 "SSLv2Hello"); |
67 new ProtocolVersion(0x0002, "SSLv2Hello"); |
67 |
68 |
68 // SSL 3.0 |
69 // SSL 3.0 |
69 final static ProtocolVersion SSL30 = new ProtocolVersion(0x0300, "SSLv3"); |
70 final static ProtocolVersion SSL30 = new ProtocolVersion(0x0300, "SSLv3"); |
70 |
71 |
71 // TLS 1.0 |
72 // TLS 1.0 |
75 final static ProtocolVersion TLS11 = new ProtocolVersion(0x0302, "TLSv1.1"); |
76 final static ProtocolVersion TLS11 = new ProtocolVersion(0x0302, "TLSv1.1"); |
76 |
77 |
77 // TLS 1.2 |
78 // TLS 1.2 |
78 final static ProtocolVersion TLS12 = new ProtocolVersion(0x0303, "TLSv1.2"); |
79 final static ProtocolVersion TLS12 = new ProtocolVersion(0x0303, "TLSv1.2"); |
79 |
80 |
|
81 // DTLS 1.0 |
|
82 // {254, 255}, the version value of DTLS 1.0. |
|
83 final static ProtocolVersion DTLS10 = |
|
84 new ProtocolVersion(0xFEFF, "DTLSv1.0"); |
|
85 |
|
86 // No DTLS 1.1, that version number was skipped in order to harmonize |
|
87 // version numbers with TLS. |
|
88 |
|
89 // DTLS 1.2 |
|
90 // {254, 253}, the version value of DTLS 1.2. |
|
91 final static ProtocolVersion DTLS12 = |
|
92 new ProtocolVersion(0xFEFD, "DTLSv1.2"); |
|
93 |
80 private static final boolean FIPS = SunJSSE.isFIPS(); |
94 private static final boolean FIPS = SunJSSE.isFIPS(); |
81 |
95 |
82 // minimum version we implement (SSL 3.0) |
96 // minimum version we implement (SSL 3.0) |
83 final static ProtocolVersion MIN = FIPS ? TLS10 : SSL30; |
97 final static ProtocolVersion MIN = FIPS ? TLS10 : SSL30; |
84 |
98 |
85 // maximum version we implement (TLS 1.2) |
99 // maximum version we implement (TLS 1.2) |
86 final static ProtocolVersion MAX = TLS12; |
100 final static ProtocolVersion MAX = TLS12; |
87 |
101 |
88 // ProtocolVersion to use by default (TLS 1.2) |
102 // SSL/TLS ProtocolVersion to use by default (TLS 1.2) |
89 final static ProtocolVersion DEFAULT = TLS12; |
103 final static ProtocolVersion DEFAULT_TLS = TLS12; |
|
104 |
|
105 // DTLS ProtocolVersion to use by default (TLS 1.2) |
|
106 final static ProtocolVersion DEFAULT_DTLS = DTLS12; |
90 |
107 |
91 // Default version for hello messages (SSLv2Hello) |
108 // Default version for hello messages (SSLv2Hello) |
92 final static ProtocolVersion DEFAULT_HELLO = FIPS ? TLS10 : SSL30; |
109 final static ProtocolVersion DEFAULT_HELLO = FIPS ? TLS10 : SSL30; |
93 |
110 |
94 // Available protocols |
111 // Available protocols |
106 // name used in JSSE (e.g. TLSv1 for TLS 1.0) |
123 // name used in JSSE (e.g. TLSv1 for TLS 1.0) |
107 final String name; |
124 final String name; |
108 |
125 |
109 // Initialize the available protocols. |
126 // Initialize the available protocols. |
110 static { |
127 static { |
111 Set<ProtocolVersion> protocols = new HashSet<>(5); |
128 Set<ProtocolVersion> protocols = new HashSet<>(7); |
112 |
129 |
113 ProtocolVersion[] pvs = new ProtocolVersion[] { |
130 ProtocolVersion[] pvs = new ProtocolVersion[] { |
114 SSL20Hello, SSL30, TLS10, TLS11, TLS12}; |
131 SSL20Hello, SSL30, TLS10, TLS11, TLS12, DTLS10, DTLS12}; |
115 EnumSet<CryptoPrimitive> cryptoPrimitives = |
132 EnumSet<CryptoPrimitive> cryptoPrimitives = |
116 EnumSet.<CryptoPrimitive>of(CryptoPrimitive.KEY_AGREEMENT); |
133 EnumSet.<CryptoPrimitive>of(CryptoPrimitive.KEY_AGREEMENT); |
117 for (ProtocolVersion p : pvs) { |
134 for (ProtocolVersion p : pvs) { |
118 if (SSLAlgorithmConstraints.DEFAULT_SSL_ONLY.permits( |
135 if (SSLAlgorithmConstraints.DEFAULT_SSL_ONLY.permits( |
119 cryptoPrimitives, p.name, null)) { |
136 cryptoPrimitives, p.name, null)) { |
143 return TLS11; |
160 return TLS11; |
144 } else if (v == TLS12.v) { |
161 } else if (v == TLS12.v) { |
145 return TLS12; |
162 return TLS12; |
146 } else if (v == SSL20Hello.v) { |
163 } else if (v == SSL20Hello.v) { |
147 return SSL20Hello; |
164 return SSL20Hello; |
|
165 } else if (v == DTLS10.v) { |
|
166 return DTLS10; |
|
167 } else if (v == DTLS12.v) { |
|
168 return DTLS12; |
148 } else { |
169 } else { |
149 int major = (v >>> 8) & 0xFF; |
170 int major = (v >>> 8) & 0xFF; |
150 int minor = v & 0xFF; |
171 int minor = v & 0xFF; |
151 return new ProtocolVersion(v, "Unknown-" + major + "." + minor); |
172 return new ProtocolVersion(v, "Unknown-" + major + "." + minor); |
152 } |
173 } |
170 if (name == null) { |
191 if (name == null) { |
171 throw new IllegalArgumentException("Protocol cannot be null"); |
192 throw new IllegalArgumentException("Protocol cannot be null"); |
172 } |
193 } |
173 |
194 |
174 if (FIPS && (name.equals(SSL30.name) || name.equals(SSL20Hello.name))) { |
195 if (FIPS && (name.equals(SSL30.name) || name.equals(SSL20Hello.name))) { |
175 throw new IllegalArgumentException |
196 throw new IllegalArgumentException( |
176 ("Only TLS 1.0 or later allowed in FIPS mode"); |
197 "Only TLS 1.0 or later allowed in FIPS mode"); |
177 } |
198 } |
178 |
199 |
179 if (name.equals(SSL30.name)) { |
200 if (name.equals(SSL30.name)) { |
180 return SSL30; |
201 return SSL30; |
181 } else if (name.equals(TLS10.name)) { |
202 } else if (name.equals(TLS10.name)) { |
199 /** |
224 /** |
200 * Compares this object with the specified object for order. |
225 * Compares this object with the specified object for order. |
201 */ |
226 */ |
202 @Override |
227 @Override |
203 public int compareTo(ProtocolVersion protocolVersion) { |
228 public int compareTo(ProtocolVersion protocolVersion) { |
204 return this.v - protocolVersion.v; |
229 if (maybeDTLSProtocol()) { |
|
230 if (!protocolVersion.maybeDTLSProtocol()) { |
|
231 throw new IllegalArgumentException("Not DTLS protocol"); |
|
232 } |
|
233 |
|
234 return protocolVersion.v - this.v; |
|
235 } else { |
|
236 if (protocolVersion.maybeDTLSProtocol()) { |
|
237 throw new IllegalArgumentException("Not TLS protocol"); |
|
238 } |
|
239 |
|
240 return this.v - protocolVersion.v; |
|
241 } |
|
242 } |
|
243 |
|
244 /** |
|
245 * Returns true if a ProtocolVersion represents a DTLS protocol. |
|
246 */ |
|
247 boolean isDTLSProtocol() { |
|
248 return this.v == DTLS12.v || this.v == DTLS10.v; |
|
249 } |
|
250 |
|
251 /** |
|
252 * Returns true if a ProtocolVersion may represent a DTLS protocol. |
|
253 */ |
|
254 boolean maybeDTLSProtocol() { |
|
255 return (this.major & 0x80) != 0; |
|
256 } |
|
257 |
|
258 boolean useTLS12PlusSpec() { |
|
259 return maybeDTLSProtocol() ? (this.v <= DTLS12.v) : (this.v >= TLS12.v); |
|
260 } |
|
261 |
|
262 boolean useTLS11PlusSpec() { |
|
263 return maybeDTLSProtocol() ? true : (this.v >= TLS11.v); |
|
264 } |
|
265 |
|
266 boolean useTLS10PlusSpec() { |
|
267 return maybeDTLSProtocol() ? true : (this.v >= TLS10.v); |
|
268 } |
|
269 |
|
270 boolean obsoletes(CipherSuite suite) { |
|
271 ProtocolVersion proto = this; |
|
272 if (proto.isDTLSProtocol()) { |
|
273 // DTLS bans stream ciphers. |
|
274 if (suite.cipher.cipherType == CipherType.STREAM_CIPHER) { |
|
275 return true; |
|
276 } |
|
277 |
|
278 proto = mapToTLSProtocol(this); |
|
279 } |
|
280 |
|
281 return (proto.v >= suite.obsoleted); |
|
282 } |
|
283 |
|
284 boolean supports(CipherSuite suite) { |
|
285 ProtocolVersion proto = this; |
|
286 if (proto.isDTLSProtocol()) { |
|
287 // DTLS bans stream ciphers. |
|
288 if (suite.cipher.cipherType == CipherType.STREAM_CIPHER) { |
|
289 return false; |
|
290 } |
|
291 |
|
292 proto = mapToTLSProtocol(this); |
|
293 } |
|
294 |
|
295 return (proto.v >= suite.supported); |
|
296 } |
|
297 |
|
298 // Map a specified protocol to the corresponding TLS version. |
|
299 // |
|
300 // DTLS 1.2 -> TLS 1.2 |
|
301 // DTLS 1.0 -> TLS 1.1 |
|
302 private static ProtocolVersion mapToTLSProtocol( |
|
303 ProtocolVersion protocolVersion) { |
|
304 |
|
305 if (protocolVersion.isDTLSProtocol()) { |
|
306 if (protocolVersion.v == DTLS10.v) { |
|
307 protocolVersion = TLS11; |
|
308 } else { // DTLS12 |
|
309 protocolVersion = TLS12; |
|
310 } |
|
311 } |
|
312 |
|
313 return protocolVersion; |
205 } |
314 } |
206 } |
315 } |