1 /* 2 * Copyright (c) 2019, 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 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 }