26 package sun.security.ssl; |
26 package sun.security.ssl; |
27 |
27 |
28 import java.io.IOException; |
28 import java.io.IOException; |
29 import java.nio.ByteBuffer; |
29 import java.nio.ByteBuffer; |
30 import java.security.AlgorithmConstraints; |
30 import java.security.AlgorithmConstraints; |
31 import java.security.AlgorithmParameters; |
|
32 import java.security.CryptoPrimitive; |
|
33 import java.security.spec.ECGenParameterSpec; |
|
34 import java.security.spec.InvalidParameterSpecException; |
|
35 import java.text.MessageFormat; |
31 import java.text.MessageFormat; |
36 import java.util.ArrayList; |
32 import java.util.ArrayList; |
37 import java.util.Collections; |
33 import java.util.Collections; |
38 import java.util.EnumSet; |
|
39 import java.util.LinkedList; |
34 import java.util.LinkedList; |
40 import java.util.List; |
35 import java.util.List; |
41 import java.util.Locale; |
36 import java.util.Locale; |
42 import javax.net.ssl.SSLProtocolException; |
37 import javax.net.ssl.SSLProtocolException; |
43 import sun.security.action.GetPropertyAction; |
38 import sun.security.action.GetPropertyAction; |
44 import sun.security.ssl.NamedGroup.NamedGroupType; |
39 import sun.security.ssl.NamedGroup.NamedGroupSpec; |
45 import static sun.security.ssl.SSLExtension.CH_SUPPORTED_GROUPS; |
40 import static sun.security.ssl.SSLExtension.CH_SUPPORTED_GROUPS; |
46 import static sun.security.ssl.SSLExtension.EE_SUPPORTED_GROUPS; |
41 import static sun.security.ssl.SSLExtension.EE_SUPPORTED_GROUPS; |
47 import sun.security.ssl.SSLExtension.ExtensionConsumer; |
42 import sun.security.ssl.SSLExtension.ExtensionConsumer; |
48 import sun.security.ssl.SSLExtension.SSLExtensionSpec; |
43 import sun.security.ssl.SSLExtension.SSLExtensionSpec; |
49 import sun.security.ssl.SSLHandshake.HandshakeMessage; |
44 import sun.security.ssl.SSLHandshake.HandshakeMessage; |
186 for (String group : groups) { |
181 for (String group : groups) { |
187 group = group.trim(); |
182 group = group.trim(); |
188 if (!group.isEmpty()) { |
183 if (!group.isEmpty()) { |
189 NamedGroup namedGroup = NamedGroup.nameOf(group); |
184 NamedGroup namedGroup = NamedGroup.nameOf(group); |
190 if (namedGroup != null) { |
185 if (namedGroup != null) { |
191 if (isAvailableGroup(namedGroup)) { |
186 if (namedGroup.isAvailable) { |
192 groupList.add(namedGroup); |
187 groupList.add(namedGroup); |
193 } |
188 } |
194 } // ignore unknown groups |
189 } // ignore unknown groups |
195 } |
190 } |
196 } |
191 } |
233 NamedGroup.FFDHE_8192, |
228 NamedGroup.FFDHE_8192, |
234 }; |
229 }; |
235 |
230 |
236 groupList = new ArrayList<>(groups.length); |
231 groupList = new ArrayList<>(groups.length); |
237 for (NamedGroup group : groups) { |
232 for (NamedGroup group : groups) { |
238 if (isAvailableGroup(group)) { |
233 if (group.isAvailable) { |
239 groupList.add(group); |
234 groupList.add(group); |
240 } |
235 } |
241 } |
236 } |
242 |
237 |
243 if (groupList.isEmpty() && |
238 if (groupList.isEmpty() && |
251 for (NamedGroup namedGroup : groupList) { |
246 for (NamedGroup namedGroup : groupList) { |
252 supportedNamedGroups[i++] = namedGroup; |
247 supportedNamedGroups[i++] = namedGroup; |
253 } |
248 } |
254 } |
249 } |
255 |
250 |
256 // check whether the group is supported by the underlying providers |
|
257 private static boolean isAvailableGroup(NamedGroup namedGroup) { |
|
258 return namedGroup.isAvailableGroup(); |
|
259 } |
|
260 |
|
261 static ECGenParameterSpec getECGenParamSpec(NamedGroup ng) { |
|
262 if (ng.type != NamedGroupType.NAMED_GROUP_ECDHE) { |
|
263 throw new RuntimeException( |
|
264 "Not a named EC group: " + ng); |
|
265 } |
|
266 |
|
267 // parameters are non-null |
|
268 AlgorithmParameters params = ng.getParameters(); |
|
269 try { |
|
270 return params.getParameterSpec(ECGenParameterSpec.class); |
|
271 } catch (InvalidParameterSpecException ipse) { |
|
272 // should be unlikely |
|
273 return new ECGenParameterSpec(ng.oid); |
|
274 } |
|
275 } |
|
276 |
|
277 static AlgorithmParameters getParameters(NamedGroup ng) { |
|
278 return ng.getParameters(); |
|
279 } |
|
280 |
|
281 // Is there any supported group permitted by the constraints? |
251 // Is there any supported group permitted by the constraints? |
282 static boolean isActivatable( |
252 static boolean isActivatable( |
283 AlgorithmConstraints constraints, NamedGroupType type) { |
253 AlgorithmConstraints constraints, NamedGroupSpec type) { |
284 |
254 |
285 boolean hasFFDHEGroups = false; |
255 boolean hasFFDHEGroups = false; |
286 for (NamedGroup namedGroup : supportedNamedGroups) { |
256 for (NamedGroup namedGroup : supportedNamedGroups) { |
287 if (namedGroup.type == type) { |
257 if (namedGroup.isAvailable && namedGroup.spec == type) { |
288 if (constraints.permits( |
258 if (namedGroup.isPermitted(constraints)) { |
289 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), |
|
290 namedGroup.algorithm, |
|
291 getParameters(namedGroup))) { |
|
292 |
|
293 return true; |
259 return true; |
294 } |
260 } |
295 |
261 |
296 if (!hasFFDHEGroups && |
262 if (!hasFFDHEGroups && |
297 (type == NamedGroupType.NAMED_GROUP_FFDHE)) { |
263 (type == NamedGroupSpec.NAMED_GROUP_FFDHE)) { |
298 hasFFDHEGroups = true; |
264 hasFFDHEGroups = true; |
299 } |
265 } |
300 } |
266 } |
301 } |
267 } |
302 |
268 |
304 // compatible mode (using DHE cipher suite without FFDHE extension) |
270 // compatible mode (using DHE cipher suite without FFDHE extension) |
305 // is allowed. |
271 // is allowed. |
306 // |
272 // |
307 // Note that the constraints checking on DHE parameters will be |
273 // Note that the constraints checking on DHE parameters will be |
308 // performed during key exchanging in a handshake. |
274 // performed during key exchanging in a handshake. |
309 return !hasFFDHEGroups && type == NamedGroupType.NAMED_GROUP_FFDHE; |
275 return !hasFFDHEGroups && type == NamedGroupSpec.NAMED_GROUP_FFDHE; |
310 } |
276 } |
311 |
277 |
312 // Is the named group permitted by the constraints? |
278 // Is the named group permitted by the constraints? |
313 static boolean isActivatable( |
279 static boolean isActivatable( |
314 AlgorithmConstraints constraints, NamedGroup namedGroup) { |
280 AlgorithmConstraints constraints, NamedGroup namedGroup) { |
315 if (!isSupported(namedGroup)) { |
281 if (!namedGroup.isAvailable || !isSupported(namedGroup)) { |
316 return false; |
282 return false; |
317 } |
283 } |
318 |
284 |
319 return constraints.permits( |
285 return namedGroup.isPermitted(constraints); |
320 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), |
|
321 namedGroup.algorithm, |
|
322 getParameters(namedGroup)); |
|
323 } |
286 } |
324 |
287 |
325 // Is the named group supported? |
288 // Is the named group supported? |
326 static boolean isSupported(NamedGroup namedGroup) { |
289 static boolean isSupported(NamedGroup namedGroup) { |
327 for (NamedGroup group : supportedNamedGroups) { |
290 for (NamedGroup group : supportedNamedGroups) { |
333 return false; |
296 return false; |
334 } |
297 } |
335 |
298 |
336 static NamedGroup getPreferredGroup( |
299 static NamedGroup getPreferredGroup( |
337 ProtocolVersion negotiatedProtocol, |
300 ProtocolVersion negotiatedProtocol, |
338 AlgorithmConstraints constraints, NamedGroupType[] types, |
301 AlgorithmConstraints constraints, NamedGroupSpec[] types, |
339 List<NamedGroup> requestedNamedGroups) { |
302 List<NamedGroup> requestedNamedGroups) { |
340 for (NamedGroup namedGroup : requestedNamedGroups) { |
303 for (NamedGroup namedGroup : requestedNamedGroups) { |
341 if ((NamedGroupType.arrayContains(types, namedGroup.type)) && |
304 if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) && |
342 namedGroup.isAvailable(negotiatedProtocol) && |
305 namedGroup.isAvailable(negotiatedProtocol) && |
343 isSupported(namedGroup) && |
306 isSupported(namedGroup) && |
344 constraints.permits( |
307 namedGroup.isPermitted(constraints)) { |
345 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), |
|
346 namedGroup.algorithm, |
|
347 getParameters(namedGroup))) { |
|
348 return namedGroup; |
308 return namedGroup; |
349 } |
309 } |
350 } |
310 } |
351 |
311 |
352 return null; |
312 return null; |
353 } |
313 } |
354 |
314 |
355 static NamedGroup getPreferredGroup( |
315 static NamedGroup getPreferredGroup( |
356 ProtocolVersion negotiatedProtocol, |
316 ProtocolVersion negotiatedProtocol, |
357 AlgorithmConstraints constraints, NamedGroupType[] types) { |
317 AlgorithmConstraints constraints, NamedGroupSpec[] types) { |
358 for (NamedGroup namedGroup : supportedNamedGroups) { |
318 for (NamedGroup namedGroup : supportedNamedGroups) { |
359 if ((NamedGroupType.arrayContains(types, namedGroup.type)) && |
319 if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) && |
360 namedGroup.isAvailable(negotiatedProtocol) && |
320 namedGroup.isAvailable(negotiatedProtocol) && |
361 constraints.permits( |
321 namedGroup.isPermitted(constraints)) { |
362 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), |
|
363 namedGroup.algorithm, |
|
364 getParameters(namedGroup))) { |
|
365 return namedGroup; |
322 return namedGroup; |
366 } |
323 } |
367 } |
324 } |
368 |
325 |
369 return null; |
326 return null; |
399 // Produce the extension. |
356 // Produce the extension. |
400 ArrayList<NamedGroup> namedGroups = |
357 ArrayList<NamedGroup> namedGroups = |
401 new ArrayList<>(SupportedGroups.supportedNamedGroups.length); |
358 new ArrayList<>(SupportedGroups.supportedNamedGroups.length); |
402 for (NamedGroup ng : SupportedGroups.supportedNamedGroups) { |
359 for (NamedGroup ng : SupportedGroups.supportedNamedGroups) { |
403 if ((!SupportedGroups.enableFFDHE) && |
360 if ((!SupportedGroups.enableFFDHE) && |
404 (ng.type == NamedGroupType.NAMED_GROUP_FFDHE)) { |
361 (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) { |
405 continue; |
362 continue; |
406 } |
363 } |
407 |
364 |
408 if (ng.isAvailable(chc.activeProtocols) && |
365 if (ng.isAvailable(chc.activeProtocols) && |
409 ng.isSupported(chc.activeCipherSuites) && |
366 ng.isSupported(chc.activeCipherSuites) && |
410 chc.algorithmConstraints.permits( |
367 ng.isPermitted(chc.algorithmConstraints)) { |
411 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), |
|
412 ng.algorithm, getParameters(ng))) { |
|
413 namedGroups.add(ng); |
368 namedGroups.add(ng); |
414 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
369 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
415 SSLLogger.fine( |
370 SSLLogger.fine( |
416 "Ignore inactive or disabled named group: " + ng.name); |
371 "Ignore inactive or disabled named group: " + ng.name); |
417 } |
372 } |
526 // they are currently supported by the client. |
481 // they are currently supported by the client. |
527 ArrayList<NamedGroup> namedGroups = new ArrayList<>( |
482 ArrayList<NamedGroup> namedGroups = new ArrayList<>( |
528 SupportedGroups.supportedNamedGroups.length); |
483 SupportedGroups.supportedNamedGroups.length); |
529 for (NamedGroup ng : SupportedGroups.supportedNamedGroups) { |
484 for (NamedGroup ng : SupportedGroups.supportedNamedGroups) { |
530 if ((!SupportedGroups.enableFFDHE) && |
485 if ((!SupportedGroups.enableFFDHE) && |
531 (ng.type == NamedGroupType.NAMED_GROUP_FFDHE)) { |
486 (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) { |
532 continue; |
487 continue; |
533 } |
488 } |
534 |
489 |
535 if (ng.isAvailable(shc.activeProtocols) && |
490 if (ng.isAvailable(shc.activeProtocols) && |
536 ng.isSupported(shc.activeCipherSuites) && |
491 ng.isSupported(shc.activeCipherSuites) && |
537 shc.algorithmConstraints.permits( |
492 ng.isPermitted(shc.algorithmConstraints)) { |
538 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), |
|
539 ng.algorithm, getParameters(ng))) { |
|
540 namedGroups.add(ng); |
493 namedGroups.add(ng); |
541 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
494 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
542 SSLLogger.fine( |
495 SSLLogger.fine( |
543 "Ignore inactive or disabled named group: " + ng.name); |
496 "Ignore inactive or disabled named group: " + ng.name); |
544 } |
497 } |