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