< prev index next >

src/java.base/share/classes/sun/security/ssl/NamedGroup.java

Print this page
rev 54061 : 8226374: Restrict TLS signature schemes and named groups
Reviewed-by: mullan


  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 }
< prev index next >