156 return ioe.getMessage(); |
146 return ioe.getMessage(); |
157 } |
147 } |
158 } |
148 } |
159 } |
149 } |
160 |
150 |
161 static enum NamedGroupType { |
|
162 NAMED_GROUP_ECDHE ("EC"), |
|
163 NAMED_GROUP_FFDHE ("DiffieHellman"), |
|
164 NAMED_GROUP_X25519 ("x25519"), |
|
165 NAMED_GROUP_X448 ("x448"), |
|
166 NAMED_GROUP_ARBITRARY ("EC"), |
|
167 NAMED_GROUP_NONE (""); |
|
168 |
|
169 private final String algorithm; |
|
170 |
|
171 private NamedGroupType(String algorithm) { |
|
172 this.algorithm = algorithm; |
|
173 } |
|
174 |
|
175 boolean isSupported(List<CipherSuite> cipherSuites) { |
|
176 for (CipherSuite cs : cipherSuites) { |
|
177 if (cs.keyExchange == null || |
|
178 cs.keyExchange.groupType == this) { |
|
179 return true; |
|
180 } |
|
181 } |
|
182 |
|
183 return false; |
|
184 } |
|
185 } |
|
186 |
|
187 static enum NamedGroup { |
|
188 // Elliptic Curves (RFC 4492) |
|
189 // |
|
190 // See sun.security.util.CurveDB for the OIDs |
|
191 // NIST K-163 |
|
192 SECT163_K1 (0x0001, "sect163k1", "1.3.132.0.1", |
|
193 NamedGroupType.NAMED_GROUP_ECDHE, |
|
194 ProtocolVersion.PROTOCOLS_TO_12), |
|
195 SECT163_R1 (0x0002, "sect163r1", "1.3.132.0.2", |
|
196 NamedGroupType.NAMED_GROUP_ECDHE, |
|
197 ProtocolVersion.PROTOCOLS_TO_12), |
|
198 |
|
199 // NIST B-163 |
|
200 SECT163_R2 (0x0003, "sect163r2", "1.3.132.0.15", |
|
201 NamedGroupType.NAMED_GROUP_ECDHE, |
|
202 ProtocolVersion.PROTOCOLS_TO_12), |
|
203 SECT193_R1 (0x0004, "sect193r1", "1.3.132.0.24", |
|
204 NamedGroupType.NAMED_GROUP_ECDHE, |
|
205 ProtocolVersion.PROTOCOLS_TO_12), |
|
206 SECT193_R2 (0x0005, "sect193r2", "1.3.132.0.25", |
|
207 NamedGroupType.NAMED_GROUP_ECDHE, |
|
208 ProtocolVersion.PROTOCOLS_TO_12), |
|
209 |
|
210 // NIST K-233 |
|
211 SECT233_K1 (0x0006, "sect233k1", "1.3.132.0.26", |
|
212 NamedGroupType.NAMED_GROUP_ECDHE, |
|
213 ProtocolVersion.PROTOCOLS_TO_12), |
|
214 |
|
215 // NIST B-233 |
|
216 SECT233_R1 (0x0007, "sect233r1", "1.3.132.0.27", |
|
217 NamedGroupType.NAMED_GROUP_ECDHE, |
|
218 ProtocolVersion.PROTOCOLS_TO_12), |
|
219 SECT239_K1 (0x0008, "sect239k1", "1.3.132.0.3", |
|
220 NamedGroupType.NAMED_GROUP_ECDHE, |
|
221 ProtocolVersion.PROTOCOLS_TO_12), |
|
222 |
|
223 // NIST K-283 |
|
224 SECT283_K1 (0x0009, "sect283k1", "1.3.132.0.16", |
|
225 NamedGroupType.NAMED_GROUP_ECDHE, |
|
226 ProtocolVersion.PROTOCOLS_TO_12), |
|
227 |
|
228 // NIST B-283 |
|
229 SECT283_R1 (0x000A, "sect283r1", "1.3.132.0.17", |
|
230 NamedGroupType.NAMED_GROUP_ECDHE, |
|
231 ProtocolVersion.PROTOCOLS_TO_12), |
|
232 |
|
233 // NIST K-409 |
|
234 SECT409_K1 (0x000B, "sect409k1", "1.3.132.0.36", |
|
235 NamedGroupType.NAMED_GROUP_ECDHE, |
|
236 ProtocolVersion.PROTOCOLS_TO_12), |
|
237 |
|
238 // NIST B-409 |
|
239 SECT409_R1 (0x000C, "sect409r1", "1.3.132.0.37", |
|
240 NamedGroupType.NAMED_GROUP_ECDHE, |
|
241 ProtocolVersion.PROTOCOLS_TO_12), |
|
242 |
|
243 // NIST K-571 |
|
244 SECT571_K1 (0x000D, "sect571k1", "1.3.132.0.38", |
|
245 NamedGroupType.NAMED_GROUP_ECDHE, |
|
246 ProtocolVersion.PROTOCOLS_TO_12), |
|
247 |
|
248 // NIST B-571 |
|
249 SECT571_R1 (0x000E, "sect571r1", "1.3.132.0.39", |
|
250 NamedGroupType.NAMED_GROUP_ECDHE, |
|
251 ProtocolVersion.PROTOCOLS_TO_12), |
|
252 SECP160_K1 (0x000F, "secp160k1", "1.3.132.0.9", |
|
253 NamedGroupType.NAMED_GROUP_ECDHE, |
|
254 ProtocolVersion.PROTOCOLS_TO_12), |
|
255 SECP160_R1 (0x0010, "secp160r1", "1.3.132.0.8", |
|
256 NamedGroupType.NAMED_GROUP_ECDHE, |
|
257 ProtocolVersion.PROTOCOLS_TO_12), |
|
258 SECP160_R2 (0x0011, "secp160r2", "1.3.132.0.30", |
|
259 NamedGroupType.NAMED_GROUP_ECDHE, |
|
260 ProtocolVersion.PROTOCOLS_TO_12), |
|
261 SECP192_K1 (0x0012, "secp192k1", "1.3.132.0.31", |
|
262 NamedGroupType.NAMED_GROUP_ECDHE, |
|
263 ProtocolVersion.PROTOCOLS_TO_12), |
|
264 |
|
265 // NIST P-192 |
|
266 SECP192_R1 (0x0013, "secp192r1", "1.2.840.10045.3.1.1", |
|
267 NamedGroupType.NAMED_GROUP_ECDHE, |
|
268 ProtocolVersion.PROTOCOLS_TO_12), |
|
269 SECP224_K1 (0x0014, "secp224k1", "1.3.132.0.32", |
|
270 NamedGroupType.NAMED_GROUP_ECDHE, |
|
271 ProtocolVersion.PROTOCOLS_TO_12), |
|
272 // NIST P-224 |
|
273 SECP224_R1 (0x0015, "secp224r1", "1.3.132.0.33", |
|
274 NamedGroupType.NAMED_GROUP_ECDHE, |
|
275 ProtocolVersion.PROTOCOLS_TO_12), |
|
276 SECP256_K1 (0x0016, "secp256k1", "1.3.132.0.10", |
|
277 NamedGroupType.NAMED_GROUP_ECDHE, |
|
278 ProtocolVersion.PROTOCOLS_TO_12), |
|
279 |
|
280 // NIST P-256 |
|
281 SECP256_R1 (0x0017, "secp256r1", "1.2.840.10045.3.1.7", |
|
282 NamedGroupType.NAMED_GROUP_ECDHE, |
|
283 ProtocolVersion.PROTOCOLS_TO_13), |
|
284 |
|
285 // NIST P-384 |
|
286 SECP384_R1 (0x0018, "secp384r1", "1.3.132.0.34", |
|
287 NamedGroupType.NAMED_GROUP_ECDHE, |
|
288 ProtocolVersion.PROTOCOLS_TO_13), |
|
289 |
|
290 // NIST P-521 |
|
291 SECP521_R1 (0x0019, "secp521r1", "1.3.132.0.35", |
|
292 NamedGroupType.NAMED_GROUP_ECDHE, |
|
293 ProtocolVersion.PROTOCOLS_TO_13), |
|
294 |
|
295 // x25519 and x448 |
|
296 X25519 (0x001D, "x25519", null, |
|
297 NamedGroupType.NAMED_GROUP_X25519, |
|
298 ProtocolVersion.PROTOCOLS_TO_13), |
|
299 X448 (0x001E, "x448", null, |
|
300 NamedGroupType.NAMED_GROUP_X448, |
|
301 ProtocolVersion.PROTOCOLS_TO_13), |
|
302 |
|
303 // Finite Field Diffie-Hellman Ephemeral Parameters (RFC 7919) |
|
304 FFDHE_2048 (0x0100, "ffdhe2048", null, |
|
305 NamedGroupType.NAMED_GROUP_FFDHE, |
|
306 ProtocolVersion.PROTOCOLS_TO_13), |
|
307 FFDHE_3072 (0x0101, "ffdhe3072", null, |
|
308 NamedGroupType.NAMED_GROUP_FFDHE, |
|
309 ProtocolVersion.PROTOCOLS_TO_13), |
|
310 FFDHE_4096 (0x0102, "ffdhe4096", null, |
|
311 NamedGroupType.NAMED_GROUP_FFDHE, |
|
312 ProtocolVersion.PROTOCOLS_TO_13), |
|
313 FFDHE_6144 (0x0103, "ffdhe6144", null, |
|
314 NamedGroupType.NAMED_GROUP_FFDHE, |
|
315 ProtocolVersion.PROTOCOLS_TO_13), |
|
316 FFDHE_8192 (0x0104, "ffdhe8192", null, |
|
317 NamedGroupType.NAMED_GROUP_FFDHE, |
|
318 ProtocolVersion.PROTOCOLS_TO_13), |
|
319 |
|
320 // Elliptic Curves (RFC 4492) |
|
321 // |
|
322 // arbitrary prime and characteristic-2 curves |
|
323 ARBITRARY_PRIME (0xFF01, "arbitrary_explicit_prime_curves", null, |
|
324 NamedGroupType.NAMED_GROUP_ARBITRARY, |
|
325 ProtocolVersion.PROTOCOLS_TO_12), |
|
326 ARBITRARY_CHAR2 (0xFF02, "arbitrary_explicit_char2_curves", null, |
|
327 NamedGroupType.NAMED_GROUP_ARBITRARY, |
|
328 ProtocolVersion.PROTOCOLS_TO_12); |
|
329 |
|
330 final int id; // hash + signature |
|
331 final NamedGroupType type; // group type |
|
332 final String name; // literal name |
|
333 final String oid; // object identifier of the named group |
|
334 final String algorithm; // signature algorithm |
|
335 final ProtocolVersion[] supportedProtocols; |
|
336 |
|
337 private NamedGroup(int id, String name, String oid, |
|
338 NamedGroupType namedGroupType, |
|
339 ProtocolVersion[] supportedProtocols) { |
|
340 this.id = id; |
|
341 this.type = namedGroupType; |
|
342 this.name = name; |
|
343 this.oid = oid; |
|
344 this.algorithm = namedGroupType.algorithm; |
|
345 this.supportedProtocols = supportedProtocols; |
|
346 } |
|
347 |
|
348 static NamedGroup valueOf(int id) { |
|
349 for (NamedGroup group : NamedGroup.values()) { |
|
350 if (group.id == id) { |
|
351 return group; |
|
352 } |
|
353 } |
|
354 |
|
355 return null; |
|
356 } |
|
357 |
|
358 static NamedGroup valueOf(ECParameterSpec params) { |
|
359 String oid = ECUtil.getCurveName(null, params); |
|
360 if ((oid != null) && (!oid.isEmpty())) { |
|
361 for (NamedGroup group : NamedGroup.values()) { |
|
362 if ((group.type == NamedGroupType.NAMED_GROUP_ECDHE) && |
|
363 oid.equals(group.oid)) { |
|
364 return group; |
|
365 } |
|
366 } |
|
367 } |
|
368 |
|
369 return null; |
|
370 } |
|
371 |
|
372 static NamedGroup valueOf(DHParameterSpec params) { |
|
373 for (Map.Entry<NamedGroup, AlgorithmParameters> me : |
|
374 SupportedGroups.namedGroupParams.entrySet()) { |
|
375 NamedGroup ng = me.getKey(); |
|
376 if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) { |
|
377 continue; |
|
378 } |
|
379 |
|
380 DHParameterSpec ngParams = null; |
|
381 AlgorithmParameters aps = me.getValue(); |
|
382 try { |
|
383 ngParams = aps.getParameterSpec(DHParameterSpec.class); |
|
384 } catch (InvalidParameterSpecException ipse) { |
|
385 // should be unlikely |
|
386 } |
|
387 |
|
388 if (ngParams == null) { |
|
389 continue; |
|
390 } |
|
391 |
|
392 if (ngParams.getP().equals(params.getP()) && |
|
393 ngParams.getG().equals(params.getG())) { |
|
394 return ng; |
|
395 } |
|
396 } |
|
397 |
|
398 return null; |
|
399 } |
|
400 |
|
401 static NamedGroup nameOf(String name) { |
|
402 for (NamedGroup group : NamedGroup.values()) { |
|
403 if (group.name.equals(name)) { |
|
404 return group; |
|
405 } |
|
406 } |
|
407 |
|
408 return null; |
|
409 } |
|
410 |
|
411 static String nameOf(int id) { |
|
412 for (NamedGroup group : NamedGroup.values()) { |
|
413 if (group.id == id) { |
|
414 return group.name; |
|
415 } |
|
416 } |
|
417 |
|
418 return "UNDEFINED-NAMED-GROUP(" + id + ")"; |
|
419 } |
|
420 |
|
421 boolean isAvailable(List<ProtocolVersion> protocolVersions) { |
|
422 for (ProtocolVersion pv : supportedProtocols) { |
|
423 if (protocolVersions.contains(pv)) { |
|
424 return true; |
|
425 } |
|
426 } |
|
427 return false; |
|
428 } |
|
429 |
|
430 boolean isAvailable(ProtocolVersion protocolVersion) { |
|
431 for (ProtocolVersion pv : supportedProtocols) { |
|
432 if (protocolVersion == pv) { |
|
433 return true; |
|
434 } |
|
435 } |
|
436 return false; |
|
437 } |
|
438 |
|
439 boolean isSupported(List<CipherSuite> cipherSuites) { |
|
440 for (CipherSuite cs : cipherSuites) { |
|
441 boolean isMatch = isAvailable(cs.supportedProtocols); |
|
442 if (isMatch && (cs.keyExchange == null || |
|
443 cs.keyExchange.groupType == type)) { |
|
444 return true; |
|
445 } |
|
446 } |
|
447 return false; |
|
448 } |
|
449 |
|
450 // lazy loading of parameters |
|
451 AlgorithmParameters getParameters() { |
|
452 return SupportedGroups.namedGroupParams.get(this); |
|
453 } |
|
454 |
|
455 AlgorithmParameterSpec getParameterSpec() { |
|
456 if (this.type == NamedGroupType.NAMED_GROUP_ECDHE) { |
|
457 return SupportedGroups.getECGenParamSpec(this); |
|
458 } else if (this.type == NamedGroupType.NAMED_GROUP_FFDHE) { |
|
459 return SupportedGroups.getDHParameterSpec(this); |
|
460 } |
|
461 |
|
462 return null; |
|
463 } |
|
464 } |
|
465 |
|
466 static class SupportedGroups { |
151 static class SupportedGroups { |
467 // To switch off the supported_groups extension for DHE cipher suite. |
152 // To switch off the supported_groups extension for DHE cipher suite. |
468 static final boolean enableFFDHE = |
153 static final boolean enableFFDHE = |
469 Utilities.getBooleanProperty("jsse.enableFFDHE", true); |
154 Utilities.getBooleanProperty("jsse.enableFFDHE", true); |
470 |
|
471 // cache to speed up the parameters construction |
|
472 static final Map<NamedGroup, |
|
473 AlgorithmParameters> namedGroupParams = new HashMap<>(); |
|
474 |
155 |
475 // the supported named groups |
156 // the supported named groups |
476 static final NamedGroup[] supportedNamedGroups; |
157 static final NamedGroup[] supportedNamedGroups; |
477 |
158 |
478 static { |
159 static { |
556 for (NamedGroup namedGroup : groupList) { |
235 for (NamedGroup namedGroup : groupList) { |
557 supportedNamedGroups[i++] = namedGroup; |
236 supportedNamedGroups[i++] = namedGroup; |
558 } |
237 } |
559 } |
238 } |
560 |
239 |
561 // check whether the group is supported by the underlying providers |
|
562 private static boolean isAvailableGroup(NamedGroup namedGroup) { |
|
563 AlgorithmParameters params = null; |
|
564 AlgorithmParameterSpec spec = null; |
|
565 if (namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) { |
|
566 if (namedGroup.oid != null) { |
|
567 try { |
|
568 params = AlgorithmParameters.getInstance("EC"); |
|
569 spec = new ECGenParameterSpec(namedGroup.oid); |
|
570 } catch (NoSuchAlgorithmException e) { |
|
571 return false; |
|
572 } |
|
573 } |
|
574 } else if (namedGroup.type == NamedGroupType.NAMED_GROUP_FFDHE) { |
|
575 try { |
|
576 params = AlgorithmParameters.getInstance("DiffieHellman"); |
|
577 spec = getFFDHEDHParameterSpec(namedGroup); |
|
578 } catch (NoSuchAlgorithmException e) { |
|
579 return false; |
|
580 } |
|
581 } // Otherwise, unsupported. |
|
582 |
|
583 if ((params != null) && (spec != null)) { |
|
584 try { |
|
585 params.init(spec); |
|
586 } catch (InvalidParameterSpecException e) { |
|
587 return false; |
|
588 } |
|
589 |
|
590 // cache the parameters |
|
591 namedGroupParams.put(namedGroup, params); |
|
592 |
|
593 return true; |
|
594 } |
|
595 |
|
596 return false; |
|
597 } |
|
598 |
|
599 private static DHParameterSpec getFFDHEDHParameterSpec( |
|
600 NamedGroup namedGroup) { |
|
601 DHParameterSpec spec = null; |
|
602 switch (namedGroup) { |
|
603 case FFDHE_2048: |
|
604 spec = PredefinedDHParameterSpecs.ffdheParams.get(2048); |
|
605 break; |
|
606 case FFDHE_3072: |
|
607 spec = PredefinedDHParameterSpecs.ffdheParams.get(3072); |
|
608 break; |
|
609 case FFDHE_4096: |
|
610 spec = PredefinedDHParameterSpecs.ffdheParams.get(4096); |
|
611 break; |
|
612 case FFDHE_6144: |
|
613 spec = PredefinedDHParameterSpecs.ffdheParams.get(6144); |
|
614 break; |
|
615 case FFDHE_8192: |
|
616 spec = PredefinedDHParameterSpecs.ffdheParams.get(8192); |
|
617 } |
|
618 |
|
619 return spec; |
|
620 } |
|
621 |
|
622 private static DHParameterSpec getPredefinedDHParameterSpec( |
|
623 NamedGroup namedGroup) { |
|
624 DHParameterSpec spec = null; |
|
625 switch (namedGroup) { |
|
626 case FFDHE_2048: |
|
627 spec = PredefinedDHParameterSpecs.definedParams.get(2048); |
|
628 break; |
|
629 case FFDHE_3072: |
|
630 spec = PredefinedDHParameterSpecs.definedParams.get(3072); |
|
631 break; |
|
632 case FFDHE_4096: |
|
633 spec = PredefinedDHParameterSpecs.definedParams.get(4096); |
|
634 break; |
|
635 case FFDHE_6144: |
|
636 spec = PredefinedDHParameterSpecs.definedParams.get(6144); |
|
637 break; |
|
638 case FFDHE_8192: |
|
639 spec = PredefinedDHParameterSpecs.definedParams.get(8192); |
|
640 } |
|
641 |
|
642 return spec; |
|
643 } |
|
644 |
|
645 static ECGenParameterSpec getECGenParamSpec(NamedGroup namedGroup) { |
|
646 if (namedGroup.type != NamedGroupType.NAMED_GROUP_ECDHE) { |
|
647 throw new RuntimeException( |
|
648 "Not a named EC group: " + namedGroup); |
|
649 } |
|
650 |
|
651 AlgorithmParameters params = namedGroupParams.get(namedGroup); |
|
652 if (params == null) { |
|
653 throw new RuntimeException( |
|
654 "Not a supported EC named group: " + namedGroup); |
|
655 } |
|
656 |
|
657 try { |
|
658 return params.getParameterSpec(ECGenParameterSpec.class); |
|
659 } catch (InvalidParameterSpecException ipse) { |
|
660 // should be unlikely |
|
661 return new ECGenParameterSpec(namedGroup.oid); |
|
662 } |
|
663 } |
|
664 |
|
665 static DHParameterSpec getDHParameterSpec(NamedGroup namedGroup) { |
|
666 if (namedGroup.type != NamedGroupType.NAMED_GROUP_FFDHE) { |
|
667 throw new RuntimeException( |
|
668 "Not a named DH group: " + namedGroup); |
|
669 } |
|
670 |
|
671 AlgorithmParameters params = namedGroupParams.get(namedGroup); |
|
672 if (params == null) { |
|
673 throw new RuntimeException( |
|
674 "Not a supported DH named group: " + namedGroup); |
|
675 } |
|
676 |
|
677 try { |
|
678 return params.getParameterSpec(DHParameterSpec.class); |
|
679 } catch (InvalidParameterSpecException ipse) { |
|
680 // should be unlikely |
|
681 return getPredefinedDHParameterSpec(namedGroup); |
|
682 } |
|
683 } |
|
684 |
|
685 // Is there any supported group permitted by the constraints? |
240 // Is there any supported group permitted by the constraints? |
686 static boolean isActivatable( |
241 static boolean isActivatable( |
687 AlgorithmConstraints constraints, NamedGroupType type) { |
242 AlgorithmConstraints constraints, NamedGroupSpec type) { |
688 |
243 |
689 boolean hasFFDHEGroups = false; |
244 boolean hasFFDHEGroups = false; |
690 for (NamedGroup namedGroup : supportedNamedGroups) { |
245 for (NamedGroup namedGroup : supportedNamedGroups) { |
691 if (namedGroup.type == type) { |
246 if (namedGroup.isAvailable && namedGroup.spec == type) { |
692 if (constraints.permits( |
247 if (namedGroup.isPermitted(constraints)) { |
693 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), |
|
694 namedGroup.algorithm, |
|
695 namedGroupParams.get(namedGroup))) { |
|
696 |
|
697 return true; |
248 return true; |
698 } |
249 } |
699 |
250 |
700 if (!hasFFDHEGroups && |
251 if (!hasFFDHEGroups && |
701 (type == NamedGroupType.NAMED_GROUP_FFDHE)) { |
252 (type == NamedGroupSpec.NAMED_GROUP_FFDHE)) { |
702 hasFFDHEGroups = true; |
253 hasFFDHEGroups = true; |
703 } |
254 } |
704 } |
255 } |
705 } |
256 } |
706 |
257 |