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 package sun.security.ssl;
26
27 import javax.crypto.spec.DHParameterSpec;
28 import javax.net.ssl.SSLException;
29 import java.io.IOException;
30 import java.security.*;
31 import java.security.spec.*;
32 import java.util.EnumSet;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Optional;
36 import java.util.concurrent.ConcurrentHashMap;
37 import javax.crypto.*;
38 import sun.security.ssl.DHKeyExchange.DHEPossession;
39 import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
40
41 import sun.security.util.ECUtil;
42
43 /**
44 * An enum containing all known named groups for use in TLS.
45 *
46 * The enum also contains the required properties of each group and the
47 * required functions (e.g. encoding/decoding).
48 */
49 enum NamedGroup {
50 // Elliptic Curves (RFC 4492)
51 //
52 // See sun.security.util.CurveDB for the OIDs
53 // NIST K-163
54
55 SECT163_K1(0x0001, "sect163k1", "1.3.132.0.1", true,
56 NamedGroupType.NAMED_GROUP_ECDHE,
57 ProtocolVersion.PROTOCOLS_TO_12),
58 SECT163_R1(0x0002, "sect163r1", "1.3.132.0.2", false,
59 NamedGroupType.NAMED_GROUP_ECDHE,
60 ProtocolVersion.PROTOCOLS_TO_12),
61
62 // NIST B-163
63 SECT163_R2(0x0003, "sect163r2", "1.3.132.0.15", true,
64 NamedGroupType.NAMED_GROUP_ECDHE,
65 ProtocolVersion.PROTOCOLS_TO_12),
66 SECT193_R1(0x0004, "sect193r1", "1.3.132.0.24", false,
67 NamedGroupType.NAMED_GROUP_ECDHE,
68 ProtocolVersion.PROTOCOLS_TO_12),
69 SECT193_R2(0x0005, "sect193r2", "1.3.132.0.25", false,
70 NamedGroupType.NAMED_GROUP_ECDHE,
71 ProtocolVersion.PROTOCOLS_TO_12),
72
73 // NIST K-233
74 SECT233_K1(0x0006, "sect233k1", "1.3.132.0.26", true,
75 NamedGroupType.NAMED_GROUP_ECDHE,
76 ProtocolVersion.PROTOCOLS_TO_12),
77
78 // NIST B-233
79 SECT233_R1(0x0007, "sect233r1", "1.3.132.0.27", true,
80 NamedGroupType.NAMED_GROUP_ECDHE,
81 ProtocolVersion.PROTOCOLS_TO_12),
82 SECT239_K1(0x0008, "sect239k1", "1.3.132.0.3", false,
83 NamedGroupType.NAMED_GROUP_ECDHE,
84 ProtocolVersion.PROTOCOLS_TO_12),
85
86 // NIST K-283
87 SECT283_K1(0x0009, "sect283k1", "1.3.132.0.16", true,
88 NamedGroupType.NAMED_GROUP_ECDHE,
89 ProtocolVersion.PROTOCOLS_TO_12),
90
91 // NIST B-283
92 SECT283_R1(0x000A, "sect283r1", "1.3.132.0.17", true,
93 NamedGroupType.NAMED_GROUP_ECDHE,
94 ProtocolVersion.PROTOCOLS_TO_12),
95
96 // NIST K-409
97 SECT409_K1(0x000B, "sect409k1", "1.3.132.0.36", true,
98 NamedGroupType.NAMED_GROUP_ECDHE,
99 ProtocolVersion.PROTOCOLS_TO_12),
100
101 // NIST B-409
102 SECT409_R1(0x000C, "sect409r1", "1.3.132.0.37", true,
103 NamedGroupType.NAMED_GROUP_ECDHE,
104 ProtocolVersion.PROTOCOLS_TO_12),
105
106 // NIST K-571
107 SECT571_K1(0x000D, "sect571k1", "1.3.132.0.38", true,
108 NamedGroupType.NAMED_GROUP_ECDHE,
109 ProtocolVersion.PROTOCOLS_TO_12),
110
111 // NIST B-571
112 SECT571_R1(0x000E, "sect571r1", "1.3.132.0.39", true,
113 NamedGroupType.NAMED_GROUP_ECDHE,
114 ProtocolVersion.PROTOCOLS_TO_12),
115 SECP160_K1(0x000F, "secp160k1", "1.3.132.0.9", false,
116 NamedGroupType.NAMED_GROUP_ECDHE,
117 ProtocolVersion.PROTOCOLS_TO_12),
118 SECP160_R1(0x0010, "secp160r1", "1.3.132.0.8", false,
119 NamedGroupType.NAMED_GROUP_ECDHE,
120 ProtocolVersion.PROTOCOLS_TO_12),
121 SECP160_R2(0x0011, "secp160r2", "1.3.132.0.30", false,
122 NamedGroupType.NAMED_GROUP_ECDHE,
123 ProtocolVersion.PROTOCOLS_TO_12),
124 SECP192_K1(0x0012, "secp192k1", "1.3.132.0.31", false,
125 NamedGroupType.NAMED_GROUP_ECDHE,
126 ProtocolVersion.PROTOCOLS_TO_12),
127
128 // NIST P-192
129 SECP192_R1(0x0013, "secp192r1", "1.2.840.10045.3.1.1", true,
130 NamedGroupType.NAMED_GROUP_ECDHE,
131 ProtocolVersion.PROTOCOLS_TO_12),
132 SECP224_K1(0x0014, "secp224k1", "1.3.132.0.32", false,
133 NamedGroupType.NAMED_GROUP_ECDHE,
134 ProtocolVersion.PROTOCOLS_TO_12),
135
136 // NIST P-224
137 SECP224_R1(0x0015, "secp224r1", "1.3.132.0.33", true,
138 NamedGroupType.NAMED_GROUP_ECDHE,
139 ProtocolVersion.PROTOCOLS_TO_12),
140 SECP256_K1(0x0016, "secp256k1", "1.3.132.0.10", false,
141 NamedGroupType.NAMED_GROUP_ECDHE,
142 ProtocolVersion.PROTOCOLS_TO_12),
143
144 // NIST P-256
145 SECP256_R1(0x0017, "secp256r1", "1.2.840.10045.3.1.7", true,
146 NamedGroupType.NAMED_GROUP_ECDHE,
147 ProtocolVersion.PROTOCOLS_TO_13),
148
149 // NIST P-384
150 SECP384_R1(0x0018, "secp384r1", "1.3.132.0.34", true,
151 NamedGroupType.NAMED_GROUP_ECDHE,
152 ProtocolVersion.PROTOCOLS_TO_13),
153
154 // NIST P-521
155 SECP521_R1(0x0019, "secp521r1", "1.3.132.0.35", true,
156 NamedGroupType.NAMED_GROUP_ECDHE,
157 ProtocolVersion.PROTOCOLS_TO_13),
158
159 // x25519 and x448 (RFC 8422/8446)
160 X25519(0x001D, "x25519", "1.3.101.110", true,
161 NamedGroupType.NAMED_GROUP_XDH,
162 ProtocolVersion.PROTOCOLS_TO_13),
163 X448(0x001E, "x448", "1.3.101.111", true,
164 NamedGroupType.NAMED_GROUP_XDH,
165 ProtocolVersion.PROTOCOLS_TO_13),
166
167 // Finite Field Diffie-Hellman Ephemeral Parameters (RFC 7919)
168 FFDHE_2048(0x0100, "ffdhe2048", null, true,
169 NamedGroupType.NAMED_GROUP_FFDHE,
170 ProtocolVersion.PROTOCOLS_TO_13),
171 FFDHE_3072(0x0101, "ffdhe3072", null, true,
172 NamedGroupType.NAMED_GROUP_FFDHE,
173 ProtocolVersion.PROTOCOLS_TO_13),
174 FFDHE_4096(0x0102, "ffdhe4096", null, true,
175 NamedGroupType.NAMED_GROUP_FFDHE,
176 ProtocolVersion.PROTOCOLS_TO_13),
177 FFDHE_6144(0x0103, "ffdhe6144", null, true,
178 NamedGroupType.NAMED_GROUP_FFDHE,
179 ProtocolVersion.PROTOCOLS_TO_13),
180 FFDHE_8192(0x0104, "ffdhe8192", null, true,
181 NamedGroupType.NAMED_GROUP_FFDHE,
182 ProtocolVersion.PROTOCOLS_TO_13),
183
184 // Elliptic Curves (RFC 4492)
185 //
186 // arbitrary prime and characteristic-2 curves
187 ARBITRARY_PRIME(0xFF01, "arbitrary_explicit_prime_curves", null, false,
188 NamedGroupType.NAMED_GROUP_ARBITRARY,
189 ProtocolVersion.PROTOCOLS_TO_12),
190 ARBITRARY_CHAR2(0xFF02, "arbitrary_explicit_char2_curves", null, false,
191 NamedGroupType.NAMED_GROUP_ARBITRARY,
192 ProtocolVersion.PROTOCOLS_TO_12);
193
194 final int id; // hash + signature
195 final NamedGroupType type; // group type
196 final String name; // literal name
197 final String oid; // object identifier of the named group
198 final String algorithm; // signature algorithm
199 final boolean isFips; // can be used in FIPS mode?
200 final ProtocolVersion[] supportedProtocols;
201 private final NamedGroupFunctions functions; // may be null
202
203 // Constructor used for all NamedGroup types
204 private NamedGroup(int id, String name, String oid, boolean isFips,
205 NamedGroupType namedGroupType,
206 ProtocolVersion[] supportedProtocols) {
207 this.id = id;
208 this.name = name;
209 this.oid = oid;
210 this.type = namedGroupType;
211 this.isFips = isFips;
212 this.supportedProtocols = supportedProtocols;
213
214 if (this.type == NamedGroupType.NAMED_GROUP_ECDHE) {
215 this.functions = ECDHFunctions.getInstance();
216 this.algorithm = "EC";
217 } else if (this.type == NamedGroupType.NAMED_GROUP_FFDHE) {
218 this.functions = FFDHFunctions.getInstance();
219 this.algorithm = "DiffieHellman";
220 } else if (this.type == NamedGroupType.NAMED_GROUP_XDH) {
221 this.functions = XDHFunctions.getInstance();
222 this.algorithm = "XDH";
223 } else if (this.type == NamedGroupType.NAMED_GROUP_ARBITRARY) {
224 this.functions = null;
225 this.algorithm = "EC";
226 } else {
227 throw new RuntimeException("Unexpected Named Group Type");
228 }
229 }
230
231 private Optional<NamedGroupFunctions> getFunctions() {
232 return Optional.ofNullable(functions);
233 }
234
235 // The next set of methods search & retrieve NamedGroups.
236
237 static NamedGroup valueOf(int id) {
238 for (NamedGroup group : NamedGroup.values()) {
239 if (group.id == id) {
240 return group;
241 }
242 }
243
244 return null;
245 }
246
247 static NamedGroup valueOf(ECParameterSpec params) {
248 String oid = JsseJce.getNamedCurveOid(params);
249 if ((oid != null) && (!oid.isEmpty())) {
250 for (NamedGroup group : NamedGroup.values()) {
251 if ((group.type == NamedGroupType.NAMED_GROUP_ECDHE)
252 && oid.equals(group.oid)) {
253 return group;
254 }
255 }
256 }
257
258 return null;
259 }
260
261 static NamedGroup valueOf(DHParameterSpec params) {
262 for (NamedGroup ng : NamedGroup.values()) {
263 if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) {
264 continue;
265 }
266
267 DHParameterSpec ngParams = null;
268 // functions is non-null for FFDHE type
269 AlgorithmParameters aps = ng.functions.getParameters(ng);
270 if (aps == null)
271 continue;
272 try {
273 ngParams = aps.getParameterSpec(DHParameterSpec.class);
274 } catch (InvalidParameterSpecException ipse) {
275 // should be unlikely
276 }
277
278 if (ngParams == null) {
279 continue;
280 }
281
282 if (ngParams.getP().equals(params.getP())
283 && ngParams.getG().equals(params.getG())) {
284 return ng;
285 }
286 }
287
288 return null;
289 }
290
291 static NamedGroup nameOf(String name) {
292 for (NamedGroup group : NamedGroup.values()) {
293 if (group.name.equals(name)) {
294 return group;
295 }
296 }
297
298 return null;
299 }
300
301 static String nameOf(int id) {
302 for (NamedGroup group : NamedGroup.values()) {
303 if (group.id == id) {
304 return group.name;
305 }
306 }
307
308 return "UNDEFINED-NAMED-GROUP(" + id + ")";
309 }
310
311 // Are the NamedGroups available for the protocol desired?
312
313 boolean isAvailable(List<ProtocolVersion> protocolVersions) {
314 for (ProtocolVersion pv : supportedProtocols) {
315 if (protocolVersions.contains(pv)) {
316 return true;
317 }
318 }
319 return false;
320 }
321
322 boolean isAvailable(ProtocolVersion protocolVersion) {
323 for (ProtocolVersion pv : supportedProtocols) {
324 if (protocolVersion == pv) {
325 return true;
326 }
327 }
328 return false;
329 }
330
331 // Are the NamedGroups available for the ciphersuites desired?
332
333 boolean isSupported(List<CipherSuite> cipherSuites) {
334 for (CipherSuite cs : cipherSuites) {
335 boolean isMatch = isAvailable(cs.supportedProtocols);
336 if (isMatch && ((cs.keyExchange == null)
337 || (NamedGroupType.arrayContains(
338 cs.keyExchange.groupTypes, type)))) {
339 return true;
340 }
341 }
342 return false;
343 }
344
345 // lazy loading of parameters
346 AlgorithmParameters getParameters() {
347 Optional<NamedGroupFunctions> ngf = getFunctions();
348 if (ngf.isEmpty()) {
349 return null;
350 }
351 return ngf.get().getParameters(this);
352 }
353
354 // The next set of methods use the NamedGroupFunctions table
355 // to do various operations in a consistent way.
356
357 AlgorithmParameterSpec getParameterSpec() {
358 Optional<NamedGroupFunctions> ngf = getFunctions();
359 if (ngf.isEmpty()) {
360 return null;
361 }
362 return ngf.get().getParameterSpec(this);
363 }
364
365 byte[] encodePossessionPublicKey(
366 NamedGroupPossession namedGroupPossession) {
367
368 Optional<NamedGroupFunctions> ngf = getFunctions();
369 if (ngf.isEmpty()) {
370 return null;
371 }
372 return ngf.get().encodePossessionPublicKey(namedGroupPossession);
373 }
374
375 SSLCredentials decodeCredentials(byte[] encoded,
376 AlgorithmConstraints constraints,
377 ExceptionSupplier onConstraintFail)
378 throws IOException, GeneralSecurityException {
379
380 Optional<NamedGroupFunctions> ngf = getFunctions();
381 if (ngf.isEmpty()) {
382 return null;
383 }
384 return ngf.get().decodeCredentials(this, encoded, constraints,
385 onConstraintFail);
386 }
387
388 SSLPossession createPossession(SecureRandom random) {
389
390 Optional<NamedGroupFunctions> ngf = getFunctions();
391 if (ngf.isEmpty()) {
392 return null;
393 }
394 return ngf.get().createPossession(this, random);
395 }
396
397 SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
398 throws IOException {
399
400 Optional<NamedGroupFunctions> ngf = getFunctions();
401 if (ngf.isEmpty()) {
402 return null;
403 }
404 return ngf.get().createKeyDerivation(hc);
405
406 }
407
408 boolean isAvailableGroup() {
409 Optional<NamedGroupFunctions> ngfOpt = getFunctions();
410 if (ngfOpt.isEmpty()) {
411 return false;
412 }
413 NamedGroupFunctions ngf = ngfOpt.get();
414 return ngf.isAvailable(this);
415 }
416
417 enum NamedGroupType {
418 NAMED_GROUP_ECDHE, // Elliptic Curve Groups (ECDHE)
419 NAMED_GROUP_FFDHE, // Finite Field Groups (DHE)
420 NAMED_GROUP_XDH, // Finite Field Groups (XDH)
421 NAMED_GROUP_ARBITRARY, // arbitrary prime and curves (ECDHE)
422 NAMED_GROUP_NONE; // Not predefined named group
423
424 boolean isSupported(List<CipherSuite> cipherSuites) {
425 for (CipherSuite cs : cipherSuites) {
426 if (cs.keyExchange == null ||
427 arrayContains(cs.keyExchange.groupTypes, this)) {
428 return true;
429 }
430 }
431
432 return false;
433 }
434
435 static boolean arrayContains(NamedGroupType[] namedGroupTypes,
436 NamedGroupType namedGroupType) {
437 for (NamedGroupType ng : namedGroupTypes) {
438 if (ng == namedGroupType) {
439 return true;
440 }
441 }
442 return false;
443 }
444 }
445
446 interface ExceptionSupplier {
447 void apply(String s) throws SSLException;
448 }
449
450 /*
451 * A list of functions to do NamedGroup operations in a
452 * algorithm-independent and consistent way.
453 */
454 private static abstract class NamedGroupFunctions {
455
456 // cache to speed up the parameters construction
457 protected static final Map<NamedGroup, AlgorithmParameters>
458 namedGroupParams = new ConcurrentHashMap<>();
459
460 protected void checkConstraints(PublicKey publicKey,
461 AlgorithmConstraints constraints,
462 ExceptionSupplier onConstraintFail)
463 throws SSLException {
464
465 if (!constraints.permits(
466 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
467 publicKey)) {
468
469 onConstraintFail.apply("key share entry does not "
470 + "comply with algorithm constraints");
471 }
472 }
473
474 public AlgorithmParameters getParameters(NamedGroup ng) {
475
476 AlgorithmParameters result = namedGroupParams.get(ng);
477 if (result == null) {
478 Optional<AlgorithmParameters> paramsOpt = getParametersImpl(ng);
479 if (paramsOpt.isPresent()) {
480 result = paramsOpt.get();
481 namedGroupParams.put(ng, result);
482 }
483 }
484
485 return result;
486 }
487
488 public abstract byte[] encodePossessionPublicKey(
489 NamedGroupPossession namedGroupPossession);
490
491 public abstract SSLCredentials decodeCredentials(
492 NamedGroup ng, byte[] encoded,
493 AlgorithmConstraints constraints,
494 ExceptionSupplier onConstraintFail)
495 throws IOException, GeneralSecurityException;
496
497 public abstract SSLPossession createPossession(NamedGroup ng,
498 SecureRandom random);
499
500 public abstract SSLKeyDerivation createKeyDerivation(
501 HandshakeContext hc) throws IOException;
502
503 protected abstract Optional<AlgorithmParameters> getParametersImpl(
504 NamedGroup ng);
505
506 public abstract AlgorithmParameterSpec getParameterSpec(NamedGroup ng);
507
508 public abstract boolean isAvailable(NamedGroup ng);
509 }
510
511 private static class FFDHFunctions extends NamedGroupFunctions {
512
513 // lazy initialization
514 private static class FunctionsHolder {
515 private static final FFDHFunctions instance = new FFDHFunctions();
516 }
517
518 private static FFDHFunctions getInstance() {
519 return FunctionsHolder.instance;
520 }
521
522 @Override
523 public byte[] encodePossessionPublicKey(
524 NamedGroupPossession namedGroupPossession) {
525 return ((DHEPossession)namedGroupPossession).encode();
526 }
527
528 @Override
529 public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
530 AlgorithmConstraints constraints,
531 ExceptionSupplier onConstraintFail)
532 throws IOException, GeneralSecurityException {
533
534 DHKeyExchange.DHECredentials result
535 = DHKeyExchange.DHECredentials.valueOf(ng, encoded);
536
537 checkConstraints(result.getPublicKey(), constraints,
538 onConstraintFail);
539
540 return result;
541 }
542
543 @Override
544 public SSLPossession createPossession(
545 NamedGroup ng, SecureRandom random) {
546 return new DHKeyExchange.DHEPossession(ng, random);
547 }
548
549 @Override
550 public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
551 throws IOException {
552
553 return DHKeyExchange.kaGenerator.createKeyDerivation(hc);
554 }
555
556 @Override
557 public AlgorithmParameterSpec getParameterSpec(NamedGroup ng) {
558 return getDHParameterSpec(ng);
559 }
560
561 DHParameterSpec getDHParameterSpec(NamedGroup ng) {
562
563 AlgorithmParameters params = getParameters(ng);
564 try {
565 return params.getParameterSpec(DHParameterSpec.class);
566 } catch (InvalidParameterSpecException ipse) {
567 // should be unlikely
568 return getPredefinedDHParameterSpec(ng);
569 }
570 }
571
572 private static DHParameterSpec getFFDHEDHParameterSpec(
573 NamedGroup namedGroup) {
574
575 DHParameterSpec spec = null;
576 switch (namedGroup) {
577 case FFDHE_2048:
578 spec = PredefinedDHParameterSpecs.ffdheParams.get(2048);
579 break;
580 case FFDHE_3072:
581 spec = PredefinedDHParameterSpecs.ffdheParams.get(3072);
582 break;
583 case FFDHE_4096:
584 spec = PredefinedDHParameterSpecs.ffdheParams.get(4096);
585 break;
586 case FFDHE_6144:
587 spec = PredefinedDHParameterSpecs.ffdheParams.get(6144);
588 break;
589 case FFDHE_8192:
590 spec = PredefinedDHParameterSpecs.ffdheParams.get(8192);
591 }
592
593 return spec;
594 }
595
596 private static DHParameterSpec getPredefinedDHParameterSpec(
597 NamedGroup namedGroup) {
598
599 DHParameterSpec spec = null;
600 switch (namedGroup) {
601 case FFDHE_2048:
602 spec = PredefinedDHParameterSpecs.definedParams.get(2048);
603 break;
604 case FFDHE_3072:
605 spec = PredefinedDHParameterSpecs.definedParams.get(3072);
606 break;
607 case FFDHE_4096:
608 spec = PredefinedDHParameterSpecs.definedParams.get(4096);
609 break;
610 case FFDHE_6144:
611 spec = PredefinedDHParameterSpecs.definedParams.get(6144);
612 break;
613 case FFDHE_8192:
614 spec = PredefinedDHParameterSpecs.definedParams.get(8192);
615 }
616
617 return spec;
618 }
619
620 @Override
621 public boolean isAvailable(NamedGroup ng) {
622
623 AlgorithmParameters params = getParameters(ng);
624 return params != null;
625 }
626
627 @Override
628 protected Optional<AlgorithmParameters> getParametersImpl(
629 NamedGroup ng) {
630 try {
631 AlgorithmParameters params
632 = JsseJce.getAlgorithmParameters("DiffieHellman");
633 AlgorithmParameterSpec spec
634 = getFFDHEDHParameterSpec(ng);
635 params.init(spec);
636 return Optional.of(params);
637 } catch (InvalidParameterSpecException
638 | NoSuchAlgorithmException ex) {
639 return Optional.empty();
640 }
641 }
642
643 }
644
645 private static class ECDHFunctions extends NamedGroupFunctions {
646
647 // lazy initialization
648 private static class FunctionsHolder {
649 private static final ECDHFunctions instance = new ECDHFunctions();
650 }
651
652 private static ECDHFunctions getInstance() {
653 return FunctionsHolder.instance;
654 }
655
656 @Override
657 public byte[] encodePossessionPublicKey(
658 NamedGroupPossession namedGroupPossession) {
659 return ((ECDHEPossession)namedGroupPossession).encode();
660 }
661
662 @Override
663 public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
664 AlgorithmConstraints constraints,
665 ExceptionSupplier onConstraintFail)
666 throws IOException, GeneralSecurityException {
667
668 ECDHKeyExchange.ECDHECredentials result
669 = ECDHKeyExchange.ECDHECredentials.valueOf(ng, encoded);
670
671 checkConstraints(result.getPublicKey(), constraints,
672 onConstraintFail);
673
674 return result;
675 }
676
677 @Override
678 public SSLPossession createPossession(
679 NamedGroup ng, SecureRandom random) {
680 return new ECDHKeyExchange.ECDHEPossession(ng, random);
681 }
682
683 @Override
684 public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
685 throws IOException {
686
687 return ECDHKeyExchange.ecdheKAGenerator.createKeyDerivation(hc);
688 }
689
690 @Override
691 public AlgorithmParameterSpec getParameterSpec(NamedGroup ng) {
692 return SupportedGroupsExtension.SupportedGroups
693 .getECGenParamSpec(ng);
694 }
695
696 @Override
697 public boolean isAvailable(NamedGroup ng) {
698
699 AlgorithmParameters params = getParameters(ng);
700 return params != null;
701 }
702
703 @Override
704 protected Optional<AlgorithmParameters> getParametersImpl(
705 NamedGroup ng) {
706 try {
707 AlgorithmParameters params
708 = JsseJce.getAlgorithmParameters("EC");
709 AlgorithmParameterSpec spec
710 = new ECGenParameterSpec(ng.oid);
711 params.init(spec);
712 return Optional.of(params);
713 } catch (InvalidParameterSpecException
714 | NoSuchAlgorithmException ex) {
715 return Optional.empty();
716 }
717 }
718 }
719
720 private static class XDHFunctions extends NamedGroupFunctions {
721
722 // lazy initialization
723 private static class FunctionsHolder {
724 private static final XDHFunctions instance = new XDHFunctions();
725 }
726
727 private static XDHFunctions getInstance() {
728 return FunctionsHolder.instance;
729 }
730
731 @Override
732 public byte[] encodePossessionPublicKey(NamedGroupPossession poss) {
733 return ((XDHKeyExchange.XDHEPossession)poss).encode();
734 }
735
736 @Override
737 public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
738 AlgorithmConstraints constraints,
739 ExceptionSupplier onConstraintFail)
740 throws IOException, GeneralSecurityException {
741
742 XDHKeyExchange.XDHECredentials result
743 = XDHKeyExchange.XDHECredentials.valueOf(ng, encoded);
744
745 checkConstraints(result.getPublicKey(), constraints,
746 onConstraintFail);
747
748 return result;
749 }
750
751 @Override
752 public SSLPossession createPossession(
753 NamedGroup ng, SecureRandom random) {
754 return new XDHKeyExchange.XDHEPossession(ng, random);
755 }
756
757 @Override
758 public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
759 throws IOException {
760 return XDHKeyExchange.xdheKAGenerator.createKeyDerivation(hc);
761 }
762
763 @Override
764 public AlgorithmParameterSpec getParameterSpec(NamedGroup ng) {
765 return new NamedParameterSpec(ng.name);
766 }
767
768 @Override
769 public boolean isAvailable(NamedGroup ng) {
770
771 try {
772 JsseJce.getKeyAgreement(ng.algorithm);
773 return true;
774 } catch (NoSuchAlgorithmException ex) {
775 return false;
776 }
777 }
778
779 @Override
780 protected Optional<AlgorithmParameters> getParametersImpl(
781 NamedGroup ng) {
782 return Optional.empty();
783 }
784 }
785 }
|
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 package sun.security.ssl;
26
27 import javax.crypto.spec.DHParameterSpec;
28 import javax.net.ssl.SSLException;
29 import java.io.IOException;
30 import java.security.*;
31 import java.security.spec.*;
32 import java.util.Collections;
33 import java.util.EnumSet;
34 import java.util.List;
35 import java.util.Set;
36 import javax.crypto.KeyAgreement;
37 import sun.security.ssl.DHKeyExchange.DHEPossession;
38 import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
39 import sun.security.util.CurveDB;
40
41
42 /**
43 * An enum containing all known named groups for use in TLS.
44 *
45 * The enum also contains the required properties of each group and the
46 * required functions (e.g. encoding/decoding).
47 */
48 enum NamedGroup {
49 // Elliptic Curves (RFC 4492)
50 //
51 // See sun.security.util.CurveDB for the OIDs
52 // NIST K-163
53
54 SECT163_K1(0x0001, "sect163k1", true,
55 NamedGroupSpec.NAMED_GROUP_ECDHE,
56 ProtocolVersion.PROTOCOLS_TO_12,
57 CurveDB.lookup("sect163k1")),
58 SECT163_R1(0x0002, "sect163r1", false,
59 NamedGroupSpec.NAMED_GROUP_ECDHE,
60 ProtocolVersion.PROTOCOLS_TO_12,
61 CurveDB.lookup("sect163r1")),
62
63 // NIST B-163
64 SECT163_R2(0x0003, "sect163r2", true,
65 NamedGroupSpec.NAMED_GROUP_ECDHE,
66 ProtocolVersion.PROTOCOLS_TO_12,
67 CurveDB.lookup("sect163r2")),
68 SECT193_R1(0x0004, "sect193r1", false,
69 NamedGroupSpec.NAMED_GROUP_ECDHE,
70 ProtocolVersion.PROTOCOLS_TO_12,
71 CurveDB.lookup("sect193r1")),
72 SECT193_R2(0x0005, "sect193r2", false,
73 NamedGroupSpec.NAMED_GROUP_ECDHE,
74 ProtocolVersion.PROTOCOLS_TO_12,
75 CurveDB.lookup("sect193r2")),
76
77 // NIST K-233
78 SECT233_K1(0x0006, "sect233k1", true,
79 NamedGroupSpec.NAMED_GROUP_ECDHE,
80 ProtocolVersion.PROTOCOLS_TO_12,
81 CurveDB.lookup("sect233k1")),
82
83 // NIST B-233
84 SECT233_R1(0x0007, "sect233r1", true,
85 NamedGroupSpec.NAMED_GROUP_ECDHE,
86 ProtocolVersion.PROTOCOLS_TO_12,
87 CurveDB.lookup("sect233r1")),
88 SECT239_K1(0x0008, "sect239k1", false,
89 NamedGroupSpec.NAMED_GROUP_ECDHE,
90 ProtocolVersion.PROTOCOLS_TO_12,
91 CurveDB.lookup("sect239k1")),
92
93 // NIST K-283
94 SECT283_K1(0x0009, "sect283k1", true,
95 NamedGroupSpec.NAMED_GROUP_ECDHE,
96 ProtocolVersion.PROTOCOLS_TO_12,
97 CurveDB.lookup("sect283k1")),
98
99 // NIST B-283
100 SECT283_R1(0x000A, "sect283r1", true,
101 NamedGroupSpec.NAMED_GROUP_ECDHE,
102 ProtocolVersion.PROTOCOLS_TO_12,
103 CurveDB.lookup("sect283r1")),
104
105 // NIST K-409
106 SECT409_K1(0x000B, "sect409k1", true,
107 NamedGroupSpec.NAMED_GROUP_ECDHE,
108 ProtocolVersion.PROTOCOLS_TO_12,
109 CurveDB.lookup("sect409k1")),
110
111 // NIST B-409
112 SECT409_R1(0x000C, "sect409r1", true,
113 NamedGroupSpec.NAMED_GROUP_ECDHE,
114 ProtocolVersion.PROTOCOLS_TO_12,
115 CurveDB.lookup("sect409r1")),
116
117 // NIST K-571
118 SECT571_K1(0x000D, "sect571k1", true,
119 NamedGroupSpec.NAMED_GROUP_ECDHE,
120 ProtocolVersion.PROTOCOLS_TO_12,
121 CurveDB.lookup("sect571k1")),
122
123 // NIST B-571
124 SECT571_R1(0x000E, "sect571r1", true,
125 NamedGroupSpec.NAMED_GROUP_ECDHE,
126 ProtocolVersion.PROTOCOLS_TO_12,
127 CurveDB.lookup("sect571r1")),
128 SECP160_K1(0x000F, "secp160k1", false,
129 NamedGroupSpec.NAMED_GROUP_ECDHE,
130 ProtocolVersion.PROTOCOLS_TO_12,
131 CurveDB.lookup("secp160k1")),
132 SECP160_R1(0x0010, "secp160r1", false,
133 NamedGroupSpec.NAMED_GROUP_ECDHE,
134 ProtocolVersion.PROTOCOLS_TO_12,
135 CurveDB.lookup("secp160r1")),
136 SECP160_R2(0x0011, "secp160r2", false,
137 NamedGroupSpec.NAMED_GROUP_ECDHE,
138 ProtocolVersion.PROTOCOLS_TO_12,
139 CurveDB.lookup("secp160r2")),
140 SECP192_K1(0x0012, "secp192k1", false,
141 NamedGroupSpec.NAMED_GROUP_ECDHE,
142 ProtocolVersion.PROTOCOLS_TO_12,
143 CurveDB.lookup("secp192k1")),
144
145 // NIST P-192
146 SECP192_R1(0x0013, "secp192r1", true,
147 NamedGroupSpec.NAMED_GROUP_ECDHE,
148 ProtocolVersion.PROTOCOLS_TO_12,
149 CurveDB.lookup("secp192r1")),
150 SECP224_K1(0x0014, "secp224k1", false,
151 NamedGroupSpec.NAMED_GROUP_ECDHE,
152 ProtocolVersion.PROTOCOLS_TO_12,
153 CurveDB.lookup("secp224k1")),
154
155 // NIST P-224
156 SECP224_R1(0x0015, "secp224r1", true,
157 NamedGroupSpec.NAMED_GROUP_ECDHE,
158 ProtocolVersion.PROTOCOLS_TO_12,
159 CurveDB.lookup("secp224r1")),
160 SECP256_K1(0x0016, "secp256k1", false,
161 NamedGroupSpec.NAMED_GROUP_ECDHE,
162 ProtocolVersion.PROTOCOLS_TO_12,
163 CurveDB.lookup("secp256k1")),
164
165 // NIST P-256
166 SECP256_R1(0x0017, "secp256r1", true,
167 NamedGroupSpec.NAMED_GROUP_ECDHE,
168 ProtocolVersion.PROTOCOLS_TO_13,
169 CurveDB.lookup("secp256r1")),
170
171 // NIST P-384
172 SECP384_R1(0x0018, "secp384r1", true,
173 NamedGroupSpec.NAMED_GROUP_ECDHE,
174 ProtocolVersion.PROTOCOLS_TO_13,
175 CurveDB.lookup("secp384r1")),
176
177 // NIST P-521
178 SECP521_R1(0x0019, "secp521r1", true,
179 NamedGroupSpec.NAMED_GROUP_ECDHE,
180 ProtocolVersion.PROTOCOLS_TO_13,
181 CurveDB.lookup("secp521r1")),
182
183 // x25519 and x448 (RFC 8422/8446)
184 X25519(0x001D, "x25519", true,
185 NamedGroupSpec.NAMED_GROUP_XDH,
186 ProtocolVersion.PROTOCOLS_TO_13,
187 NamedParameterSpec.X25519),
188 X448(0x001E, "x448", true,
189 NamedGroupSpec.NAMED_GROUP_XDH,
190 ProtocolVersion.PROTOCOLS_TO_13,
191 NamedParameterSpec.X448),
192
193 // Finite Field Diffie-Hellman Ephemeral Parameters (RFC 7919)
194 FFDHE_2048(0x0100, "ffdhe2048", true,
195 NamedGroupSpec.NAMED_GROUP_FFDHE,
196 ProtocolVersion.PROTOCOLS_TO_13,
197 PredefinedDHParameterSpecs.ffdheParams.get(2048)),
198
199 FFDHE_3072(0x0101, "ffdhe3072", true,
200 NamedGroupSpec.NAMED_GROUP_FFDHE,
201 ProtocolVersion.PROTOCOLS_TO_13,
202 PredefinedDHParameterSpecs.ffdheParams.get(3072)),
203 FFDHE_4096(0x0102, "ffdhe4096", true,
204 NamedGroupSpec.NAMED_GROUP_FFDHE,
205 ProtocolVersion.PROTOCOLS_TO_13,
206 PredefinedDHParameterSpecs.ffdheParams.get(4096)),
207 FFDHE_6144(0x0103, "ffdhe6144", true,
208 NamedGroupSpec.NAMED_GROUP_FFDHE,
209 ProtocolVersion.PROTOCOLS_TO_13,
210 PredefinedDHParameterSpecs.ffdheParams.get(6144)),
211 FFDHE_8192(0x0104, "ffdhe8192", true,
212 NamedGroupSpec.NAMED_GROUP_FFDHE,
213 ProtocolVersion.PROTOCOLS_TO_13,
214 PredefinedDHParameterSpecs.ffdheParams.get(8192)),
215
216 // Elliptic Curves (RFC 4492)
217 //
218 // arbitrary prime and characteristic-2 curves
219 ARBITRARY_PRIME(0xFF01, "arbitrary_explicit_prime_curves", false,
220 NamedGroupSpec.NAMED_GROUP_ARBITRARY,
221 ProtocolVersion.PROTOCOLS_TO_12,
222 null),
223 ARBITRARY_CHAR2(0xFF02, "arbitrary_explicit_char2_curves", false,
224 NamedGroupSpec.NAMED_GROUP_ARBITRARY,
225 ProtocolVersion.PROTOCOLS_TO_12,
226 null);
227
228 final int id; // hash + signature
229 final String name; // literal name
230 final boolean isFips; // can be used in FIPS mode?
231 final NamedGroupSpec spec; // group type
232 final ProtocolVersion[] supportedProtocols;
233 final String algorithm; // key exchange algorithm
234 final AlgorithmParameterSpec keAlgParamSpec;
235 final AlgorithmParameters keAlgParams;
236 final boolean isAvailable;
237
238 // performance optimization
239 private static final Set<CryptoPrimitive> KEY_AGREEMENT_PRIMITIVE_SET =
240 Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.KEY_AGREEMENT));
241
242 // Constructor used for all NamedGroup types
243 private NamedGroup(int id, String name, boolean isFips,
244 NamedGroupSpec namedGroupSpec,
245 ProtocolVersion[] supportedProtocols,
246 AlgorithmParameterSpec keAlgParamSpec) {
247 this.id = id;
248 this.name = name;
249 this.isFips = isFips;
250 this.spec = namedGroupSpec;
251 this.algorithm = namedGroupSpec.algorithm;
252 this.supportedProtocols = supportedProtocols;
253 this.keAlgParamSpec = keAlgParamSpec;
254
255 AlgorithmParameters algParams = null;
256 boolean mediator = (keAlgParamSpec != null);
257 if (mediator) {
258 try {
259 algParams =
260 AlgorithmParameters.getInstance(namedGroupSpec.algorithm);
261 algParams.init(keAlgParamSpec);
262 } catch (InvalidParameterSpecException
263 | NoSuchAlgorithmException exp) {
264 if (namedGroupSpec != NamedGroupSpec.NAMED_GROUP_XDH) {
265 mediator = false;
266 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
267 SSLLogger.warning(
268 "No AlgorithmParameters for " + name, exp);
269 }
270 } else {
271 // HACK CODE
272 //
273 // Please remove the following code if the XDH/X25519/X448
274 // AlgorithmParameters algorithms are supported in JDK.
275 algParams = null;
276 try {
277 KeyAgreement.getInstance(name);
278
279 // The following service is also needed. But for
280 // performance, check the KeyAgreement impl only.
281 //
282 // KeyFactory.getInstance(name);
283 // KeyPairGenerator.getInstance(name);
284 // AlgorithmParameters.getInstance(name);
285 } catch (NoSuchAlgorithmException nsae) {
286 mediator = false;
287 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
288 SSLLogger.warning(
289 "No AlgorithmParameters for " + name, nsae);
290 }
291 }
292 }
293 }
294 }
295
296 this.isAvailable = mediator;
297 this.keAlgParams = mediator ? algParams : null;
298 }
299
300 //
301 // The next set of methods search & retrieve NamedGroups.
302 //
303 static NamedGroup valueOf(int id) {
304 for (NamedGroup group : NamedGroup.values()) {
305 if (group.id == id) {
306 return group;
307 }
308 }
309
310 return null;
311 }
312
313 static NamedGroup valueOf(ECParameterSpec params) {
314 for (NamedGroup ng : NamedGroup.values()) {
315 if (ng.spec == NamedGroupSpec.NAMED_GROUP_ECDHE) {
316 if ((params == ng.keAlgParamSpec) ||
317 (ng.keAlgParamSpec == CurveDB.lookup(params))) {
318 return ng;
319 }
320 }
321 }
322
323 return null;
324 }
325
326 static NamedGroup valueOf(DHParameterSpec params) {
327 for (NamedGroup ng : NamedGroup.values()) {
328 if (ng.spec != NamedGroupSpec.NAMED_GROUP_FFDHE) {
329 continue;
330 }
331
332 DHParameterSpec ngParams = (DHParameterSpec)ng.keAlgParamSpec;
333 if (ngParams.getP().equals(params.getP())
334 && ngParams.getG().equals(params.getG())) {
335 return ng;
336 }
337 }
338
339 return null;
340 }
341
342 static NamedGroup nameOf(String name) {
343 for (NamedGroup group : NamedGroup.values()) {
344 if (group.name.equals(name)) {
345 return group;
346 }
347 }
348
349 return null;
350 }
351
352 static String nameOf(int id) {
353 for (NamedGroup group : NamedGroup.values()) {
354 if (group.id == id) {
355 return group.name;
356 }
357 }
358
359 return "UNDEFINED-NAMED-GROUP(" + id + ")";
360 }
361
362 // Is the NamedGroup available for the protocols desired?
363 boolean isAvailable(List<ProtocolVersion> protocolVersions) {
364 if (this.isAvailable) {
365 for (ProtocolVersion pv : supportedProtocols) {
366 if (protocolVersions.contains(pv)) {
367 return true;
368 }
369 }
370 }
371
372 return false;
373 }
374
375 boolean isAvailable(ProtocolVersion protocolVersion) {
376 if (this.isAvailable) {
377 for (ProtocolVersion pv : supportedProtocols) {
378 if (protocolVersion == pv) {
379 return true;
380 }
381 }
382 }
383
384 return false;
385 }
386
387 // Are the NamedGroups available for the ciphersuites desired?
388 boolean isSupported(List<CipherSuite> cipherSuites) {
389 for (CipherSuite cs : cipherSuites) {
390 boolean isMatch = isAvailable(cs.supportedProtocols);
391 if (isMatch && ((cs.keyExchange == null)
392 || (NamedGroupSpec.arrayContains(
393 cs.keyExchange.groupTypes, spec)))) {
394 return true;
395 }
396 }
397
398 return false;
399 }
400
401 boolean isPermitted(AlgorithmConstraints constraints) {
402 return constraints.permits(KEY_AGREEMENT_PRIMITIVE_SET,
403 this.name, null) &&
404 constraints.permits(KEY_AGREEMENT_PRIMITIVE_SET,
405 this.algorithm, this.keAlgParams);
406 }
407
408 byte[] encodePossessionPublicKey(
409 NamedGroupPossession namedGroupPossession) {
410 return spec.encodePossessionPublicKey(namedGroupPossession);
411 }
412
413 SSLCredentials decodeCredentials(byte[] encoded,
414 AlgorithmConstraints constraints,
415 ExceptionSupplier onConstraintFail)
416 throws IOException, GeneralSecurityException {
417 return spec.decodeCredentials(
418 this, encoded, constraints, onConstraintFail);
419 }
420
421 SSLPossession createPossession(SecureRandom random) {
422 return spec.createPossession(this, random);
423 }
424
425 SSLKeyDerivation createKeyDerivation(
426 HandshakeContext hc) throws IOException {
427 return spec.createKeyDerivation(hc);
428 }
429
430 interface ExceptionSupplier {
431 void apply(String s) throws SSLException;
432 }
433
434 // A list of operations related to named groups.
435 private interface NamedGroupScheme {
436 default void checkConstraints(PublicKey publicKey,
437 AlgorithmConstraints constraints,
438 ExceptionSupplier onConstraintFail) throws SSLException {
439 if (!constraints.permits(
440 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), publicKey)) {
441 onConstraintFail.apply("key share entry does not "
442 + "comply with algorithm constraints");
443 }
444 }
445
446 byte[] encodePossessionPublicKey(
447 NamedGroupPossession namedGroupPossession);
448
449 SSLCredentials decodeCredentials(
450 NamedGroup ng, byte[] encoded,
451 AlgorithmConstraints constraints,
452 ExceptionSupplier onConstraintFail
453 ) throws IOException, GeneralSecurityException;
454
455 SSLPossession createPossession(NamedGroup ng, SecureRandom random);
456
457 SSLKeyDerivation createKeyDerivation(
458 HandshakeContext hc) throws IOException;
459 }
460
461 enum NamedGroupSpec implements NamedGroupScheme {
462 // Elliptic Curve Groups (ECDHE)
463 NAMED_GROUP_ECDHE("EC", ECDHEScheme.instance),
464
465 // Finite Field Groups (DHE)
466 NAMED_GROUP_FFDHE("DiffieHellman", FFDHEScheme.instance),
467
468 // Finite Field Groups (XDH)
469 NAMED_GROUP_XDH("XDH", XDHScheme.instance),
470
471 // arbitrary prime and curves (ECDHE)
472 NAMED_GROUP_ARBITRARY("EC", null),
473
474 // Not predefined named group
475 NAMED_GROUP_NONE("", null);
476
477 private final String algorithm; // key exchange name
478 private final NamedGroupScheme scheme; // named group operations
479
480 private NamedGroupSpec(String algorithm, NamedGroupScheme scheme) {
481 this.algorithm = algorithm;
482 this.scheme = scheme;
483 }
484
485 boolean isSupported(List<CipherSuite> cipherSuites) {
486 for (CipherSuite cs : cipherSuites) {
487 if (cs.keyExchange == null ||
488 arrayContains(cs.keyExchange.groupTypes, this)) {
489 return true;
490 }
491 }
492
493 return false;
494 }
495
496 static boolean arrayContains(NamedGroupSpec[] namedGroupTypes,
497 NamedGroupSpec namedGroupType) {
498 for (NamedGroupSpec ng : namedGroupTypes) {
499 if (ng == namedGroupType) {
500 return true;
501 }
502 }
503
504 return false;
505 }
506
507 @Override
508 public byte[] encodePossessionPublicKey(
509 NamedGroupPossession namedGroupPossession) {
510 if (scheme != null) {
511 return scheme.encodePossessionPublicKey(namedGroupPossession);
512 }
513
514 return null;
515 }
516
517 @Override
518 public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
519 AlgorithmConstraints constraints,
520 ExceptionSupplier onConstraintFail
521 ) throws IOException, GeneralSecurityException {
522 if (scheme != null) {
523 return scheme.decodeCredentials(
524 ng, encoded, constraints, onConstraintFail);
525 }
526
527 return null;
528 }
529
530 @Override
531 public SSLPossession createPossession(
532 NamedGroup ng, SecureRandom random) {
533 if (scheme != null) {
534 return scheme.createPossession(ng, random);
535 }
536
537 return null;
538 }
539
540 @Override
541 public SSLKeyDerivation createKeyDerivation(
542 HandshakeContext hc) throws IOException {
543 if (scheme != null) {
544 return scheme.createKeyDerivation(hc);
545 }
546
547 return null;
548 }
549 }
550
551 private static class FFDHEScheme implements NamedGroupScheme {
552 private static final FFDHEScheme instance = new FFDHEScheme();
553
554 @Override
555 public byte[] encodePossessionPublicKey(
556 NamedGroupPossession namedGroupPossession) {
557 return ((DHEPossession)namedGroupPossession).encode();
558 }
559
560 @Override
561 public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
562 AlgorithmConstraints constraints,
563 ExceptionSupplier onConstraintFail
564 ) throws IOException, GeneralSecurityException {
565
566 DHKeyExchange.DHECredentials result
567 = DHKeyExchange.DHECredentials.valueOf(ng, encoded);
568
569 checkConstraints(result.getPublicKey(), constraints,
570 onConstraintFail);
571
572 return result;
573 }
574
575 @Override
576 public SSLPossession createPossession(
577 NamedGroup ng, SecureRandom random) {
578 return new DHKeyExchange.DHEPossession(ng, random);
579 }
580
581 @Override
582 public SSLKeyDerivation createKeyDerivation(
583 HandshakeContext hc) throws IOException {
584
585 return DHKeyExchange.kaGenerator.createKeyDerivation(hc);
586 }
587 }
588
589 private static class ECDHEScheme implements NamedGroupScheme {
590 private static final ECDHEScheme instance = new ECDHEScheme();
591
592 @Override
593 public byte[] encodePossessionPublicKey(
594 NamedGroupPossession namedGroupPossession) {
595 return ((ECDHEPossession)namedGroupPossession).encode();
596 }
597
598 @Override
599 public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
600 AlgorithmConstraints constraints,
601 ExceptionSupplier onConstraintFail
602 ) throws IOException, GeneralSecurityException {
603
604 ECDHKeyExchange.ECDHECredentials result
605 = ECDHKeyExchange.ECDHECredentials.valueOf(ng, encoded);
606
607 checkConstraints(result.getPublicKey(), constraints,
608 onConstraintFail);
609
610 return result;
611 }
612
613 @Override
614 public SSLPossession createPossession(
615 NamedGroup ng, SecureRandom random) {
616 return new ECDHKeyExchange.ECDHEPossession(ng, random);
617 }
618
619 @Override
620 public SSLKeyDerivation createKeyDerivation(
621 HandshakeContext hc) throws IOException {
622 return ECDHKeyExchange.ecdheKAGenerator.createKeyDerivation(hc);
623 }
624 }
625
626 private static class XDHScheme implements NamedGroupScheme {
627 private static final XDHScheme instance = new XDHScheme();
628
629 @Override
630 public byte[] encodePossessionPublicKey(NamedGroupPossession poss) {
631 return ((XDHKeyExchange.XDHEPossession)poss).encode();
632 }
633
634 @Override
635 public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
636 AlgorithmConstraints constraints,
637 ExceptionSupplier onConstraintFail
638 ) throws IOException, GeneralSecurityException {
639
640 XDHKeyExchange.XDHECredentials result
641 = XDHKeyExchange.XDHECredentials.valueOf(ng, encoded);
642
643 checkConstraints(result.getPublicKey(), constraints,
644 onConstraintFail);
645
646 return result;
647 }
648
649 @Override
650 public SSLPossession createPossession(
651 NamedGroup ng, SecureRandom random) {
652 return new XDHKeyExchange.XDHEPossession(ng, random);
653 }
654
655 @Override
656 public SSLKeyDerivation createKeyDerivation(
657 HandshakeContext hc) throws IOException {
658 return XDHKeyExchange.xdheKAGenerator.createKeyDerivation(hc);
659 }
660 }
661 }
|