< 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
@@ -27,20 +27,19 @@
import javax.crypto.spec.DHParameterSpec;
import javax.net.ssl.SSLException;
import java.io.IOException;
import java.security.*;
import java.security.spec.*;
+import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.ConcurrentHashMap;
-import javax.crypto.*;
+import java.util.Set;
+import javax.crypto.KeyAgreement;
import sun.security.ssl.DHKeyExchange.DHEPossession;
import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
+import sun.security.util.CurveDB;
-import sun.security.util.ECUtil;
/**
* An enum containing all known named groups for use in TLS.
*
* The enum also contains the required properties of each group and the
@@ -50,192 +49,258 @@
// Elliptic Curves (RFC 4492)
//
// See sun.security.util.CurveDB for the OIDs
// NIST K-163
- SECT163_K1(0x0001, "sect163k1", "1.3.132.0.1", true,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECT163_R1(0x0002, "sect163r1", "1.3.132.0.2", false,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT163_K1(0x0001, "sect163k1", true,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect163k1")),
+ SECT163_R1(0x0002, "sect163r1", false,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect163r1")),
// NIST B-163
- SECT163_R2(0x0003, "sect163r2", "1.3.132.0.15", true,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECT193_R1(0x0004, "sect193r1", "1.3.132.0.24", false,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECT193_R2(0x0005, "sect193r2", "1.3.132.0.25", false,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT163_R2(0x0003, "sect163r2", true,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect163r2")),
+ SECT193_R1(0x0004, "sect193r1", false,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect193r1")),
+ SECT193_R2(0x0005, "sect193r2", false,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect193r2")),
// NIST K-233
- SECT233_K1(0x0006, "sect233k1", "1.3.132.0.26", true,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT233_K1(0x0006, "sect233k1", true,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect233k1")),
// NIST B-233
- SECT233_R1(0x0007, "sect233r1", "1.3.132.0.27", true,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECT239_K1(0x0008, "sect239k1", "1.3.132.0.3", false,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT233_R1(0x0007, "sect233r1", true,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect233r1")),
+ SECT239_K1(0x0008, "sect239k1", false,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect239k1")),
// NIST K-283
- SECT283_K1(0x0009, "sect283k1", "1.3.132.0.16", true,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT283_K1(0x0009, "sect283k1", true,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect163k1")),
// NIST B-283
- SECT283_R1(0x000A, "sect283r1", "1.3.132.0.17", true,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT283_R1(0x000A, "sect283r1", true,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect283r1")),
// NIST K-409
- SECT409_K1(0x000B, "sect409k1", "1.3.132.0.36", true,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT409_K1(0x000B, "sect409k1", true,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect409k1")),
// NIST B-409
- SECT409_R1(0x000C, "sect409r1", "1.3.132.0.37", true,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT409_R1(0x000C, "sect409r1", true,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect409r1")),
// NIST K-571
- SECT571_K1(0x000D, "sect571k1", "1.3.132.0.38", true,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT571_K1(0x000D, "sect571k1", true,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect571k1")),
// NIST B-571
- SECT571_R1(0x000E, "sect571r1", "1.3.132.0.39", true,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP160_K1(0x000F, "secp160k1", "1.3.132.0.9", false,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP160_R1(0x0010, "secp160r1", "1.3.132.0.8", false,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP160_R2(0x0011, "secp160r2", "1.3.132.0.30", false,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP192_K1(0x0012, "secp192k1", "1.3.132.0.31", false,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECT571_R1(0x000E, "sect571r1", true,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("sect571r1")),
+ SECP160_K1(0x000F, "secp160k1", false,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp160k1")),
+ SECP160_R1(0x0010, "secp160r1", false,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp160r1")),
+ SECP160_R2(0x0011, "secp160r2", false,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp160r2")),
+ SECP192_K1(0x0012, "secp192k1", false,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp192k1")),
// NIST P-192
- SECP192_R1(0x0013, "secp192r1", "1.2.840.10045.3.1.1", true,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP224_K1(0x0014, "secp224k1", "1.3.132.0.32", false,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECP192_R1(0x0013, "secp192r1", true,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp192r1")),
+ SECP224_K1(0x0014, "secp224k1", false,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp224k1")),
// NIST P-224
- SECP224_R1(0x0015, "secp224r1", "1.3.132.0.33", true,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
- SECP256_K1(0x0016, "secp256k1", "1.3.132.0.10", false,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_12),
+ SECP224_R1(0x0015, "secp224r1", true,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp224r1")),
+ SECP256_K1(0x0016, "secp256k1", false,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ CurveDB.lookup("secp256k1")),
// NIST P-256
- SECP256_R1(0x0017, "secp256r1", "1.2.840.10045.3.1.7", true,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
+ SECP256_R1(0x0017, "secp256r1", true,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ CurveDB.lookup("secp256r1")),
// NIST P-384
- SECP384_R1(0x0018, "secp384r1", "1.3.132.0.34", true,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
+ SECP384_R1(0x0018, "secp384r1", true,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ CurveDB.lookup("secp384r1")),
// NIST P-521
- SECP521_R1(0x0019, "secp521r1", "1.3.132.0.35", true,
- NamedGroupType.NAMED_GROUP_ECDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
+ SECP521_R1(0x0019, "secp521r1", true,
+ NamedGroupSpec.NAMED_GROUP_ECDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ CurveDB.lookup("secp521r1")),
// x25519 and x448 (RFC 8422/8446)
- X25519(0x001D, "x25519", "1.3.101.110", true,
- NamedGroupType.NAMED_GROUP_XDH,
- ProtocolVersion.PROTOCOLS_TO_13),
- X448(0x001E, "x448", "1.3.101.111", true,
- NamedGroupType.NAMED_GROUP_XDH,
- ProtocolVersion.PROTOCOLS_TO_13),
+ X25519(0x001D, "x25519", true,
+ NamedGroupSpec.NAMED_GROUP_XDH,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ NamedParameterSpec.X25519),
+ X448(0x001E, "x448", true,
+ NamedGroupSpec.NAMED_GROUP_XDH,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ NamedParameterSpec.X448),
// Finite Field Diffie-Hellman Ephemeral Parameters (RFC 7919)
- FFDHE_2048(0x0100, "ffdhe2048", null, true,
- NamedGroupType.NAMED_GROUP_FFDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
- FFDHE_3072(0x0101, "ffdhe3072", null, true,
- NamedGroupType.NAMED_GROUP_FFDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
- FFDHE_4096(0x0102, "ffdhe4096", null, true,
- NamedGroupType.NAMED_GROUP_FFDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
- FFDHE_6144(0x0103, "ffdhe6144", null, true,
- NamedGroupType.NAMED_GROUP_FFDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
- FFDHE_8192(0x0104, "ffdhe8192", null, true,
- NamedGroupType.NAMED_GROUP_FFDHE,
- ProtocolVersion.PROTOCOLS_TO_13),
+ FFDHE_2048(0x0100, "ffdhe2048", true,
+ NamedGroupSpec.NAMED_GROUP_FFDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ PredefinedDHParameterSpecs.ffdheParams.get(2048)),
+ FFDHE_3072(0x0101, "ffdhe3072", true,
+ NamedGroupSpec.NAMED_GROUP_FFDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ PredefinedDHParameterSpecs.ffdheParams.get(3072)),
+ FFDHE_4096(0x0102, "ffdhe4096", true,
+ NamedGroupSpec.NAMED_GROUP_FFDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ PredefinedDHParameterSpecs.ffdheParams.get(4096)),
+ FFDHE_6144(0x0103, "ffdhe6144", true,
+ NamedGroupSpec.NAMED_GROUP_FFDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ PredefinedDHParameterSpecs.ffdheParams.get(6144)),
+ FFDHE_8192(0x0104, "ffdhe8192", true,
+ NamedGroupSpec.NAMED_GROUP_FFDHE,
+ ProtocolVersion.PROTOCOLS_TO_13,
+ PredefinedDHParameterSpecs.ffdheParams.get(8192)),
// Elliptic Curves (RFC 4492)
//
// arbitrary prime and characteristic-2 curves
- ARBITRARY_PRIME(0xFF01, "arbitrary_explicit_prime_curves", null, false,
- NamedGroupType.NAMED_GROUP_ARBITRARY,
- ProtocolVersion.PROTOCOLS_TO_12),
- ARBITRARY_CHAR2(0xFF02, "arbitrary_explicit_char2_curves", null, false,
- NamedGroupType.NAMED_GROUP_ARBITRARY,
- ProtocolVersion.PROTOCOLS_TO_12);
+ ARBITRARY_PRIME(0xFF01, "arbitrary_explicit_prime_curves", false,
+ NamedGroupSpec.NAMED_GROUP_ARBITRARY,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ null),
+ ARBITRARY_CHAR2(0xFF02, "arbitrary_explicit_char2_curves", false,
+ NamedGroupSpec.NAMED_GROUP_ARBITRARY,
+ ProtocolVersion.PROTOCOLS_TO_12,
+ null);
final int id; // hash + signature
- final NamedGroupType type; // group type
final String name; // literal name
- final String oid; // object identifier of the named group
- final String algorithm; // signature algorithm
final boolean isFips; // can be used in FIPS mode?
+ final NamedGroupSpec spec; // group type
final ProtocolVersion[] supportedProtocols;
- private final NamedGroupFunctions functions; // may be null
+ final String algorithm; // key exchange algorithm
+ final AlgorithmParameterSpec keAlgParamSpec;
+ final AlgorithmParameters keAlgParams;
+ final boolean isAvailable;
+
+ // performance optimization
+ private static final Set<CryptoPrimitive> KEY_AGREEMENT_PRIMITIVE_SET =
+ Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.KEY_AGREEMENT));
// Constructor used for all NamedGroup types
- private NamedGroup(int id, String name, String oid, boolean isFips,
- NamedGroupType namedGroupType,
- ProtocolVersion[] supportedProtocols) {
+ private NamedGroup(int id, String name, boolean isFips,
+ NamedGroupSpec namedGroupSpec,
+ ProtocolVersion[] supportedProtocols,
+ AlgorithmParameterSpec keAlgParamSpec) {
this.id = id;
this.name = name;
- this.oid = oid;
- this.type = namedGroupType;
this.isFips = isFips;
+ this.spec = namedGroupSpec;
+ this.algorithm = namedGroupSpec.algorithm;
this.supportedProtocols = supportedProtocols;
+ this.keAlgParamSpec = keAlgParamSpec;
- if (this.type == NamedGroupType.NAMED_GROUP_ECDHE) {
- this.functions = ECDHFunctions.getInstance();
- this.algorithm = "EC";
- } else if (this.type == NamedGroupType.NAMED_GROUP_FFDHE) {
- this.functions = FFDHFunctions.getInstance();
- this.algorithm = "DiffieHellman";
- } else if (this.type == NamedGroupType.NAMED_GROUP_XDH) {
- this.functions = XDHFunctions.getInstance();
- this.algorithm = "XDH";
- } else if (this.type == NamedGroupType.NAMED_GROUP_ARBITRARY) {
- this.functions = null;
- this.algorithm = "EC";
+ AlgorithmParameters algParams = null;
+ boolean mediator = (keAlgParamSpec != null);
+ if (mediator) {
+ try {
+ algParams =
+ AlgorithmParameters.getInstance(namedGroupSpec.algorithm);
+ algParams.init(keAlgParamSpec);
+ } catch (InvalidParameterSpecException
+ | NoSuchAlgorithmException exp) {
+ if (namedGroupSpec != NamedGroupSpec.NAMED_GROUP_XDH) {
+ mediator = false;
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
+ SSLLogger.warning(
+ "No AlgorithmParameters for " + name, exp);
+ }
} else {
- throw new RuntimeException("Unexpected Named Group Type");
+ // HACK CODE
+ //
+ // Please remove the following code if the XDH/X25519/X448
+ // AlgorithmParameters algorithms are supported in JDK.
+ algParams = null;
+ try {
+ KeyAgreement.getInstance(name);
+
+ // The following service is also needed. But for
+ // performance, check the KeyAgreement impl only.
+ //
+ // KeyFactory.getInstance(name);
+ // KeyPairGenerator.getInstance(name);
+ // AlgorithmParameters.getInstance(name);
+ } catch (NoSuchAlgorithmException nsae) {
+ mediator = false;
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
+ SSLLogger.warning(
+ "No AlgorithmParameters for " + name, nsae);
+ }
+ }
+ }
}
}
- private Optional<NamedGroupFunctions> getFunctions() {
- return Optional.ofNullable(functions);
+ this.isAvailable = mediator;
+ this.keAlgParams = mediator ? algParams : null;
}
+ //
// The next set of methods search & retrieve NamedGroups.
-
+ //
static NamedGroup valueOf(int id) {
for (NamedGroup group : NamedGroup.values()) {
if (group.id == id) {
return group;
}
@@ -243,44 +308,29 @@
return null;
}
static NamedGroup valueOf(ECParameterSpec params) {
- String oid = JsseJce.getNamedCurveOid(params);
- if ((oid != null) && (!oid.isEmpty())) {
- for (NamedGroup group : NamedGroup.values()) {
- if ((group.type == NamedGroupType.NAMED_GROUP_ECDHE)
- && oid.equals(group.oid)) {
- return group;
+ for (NamedGroup ng : NamedGroup.values()) {
+ if (ng.spec == NamedGroupSpec.NAMED_GROUP_ECDHE) {
+ if ((params == ng.keAlgParamSpec) ||
+ (ng.keAlgParamSpec == CurveDB.lookup(params))) {
+ return ng;
}
}
}
return null;
}
static NamedGroup valueOf(DHParameterSpec params) {
for (NamedGroup ng : NamedGroup.values()) {
- if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) {
- continue;
- }
-
- DHParameterSpec ngParams = null;
- // functions is non-null for FFDHE type
- AlgorithmParameters aps = ng.functions.getParameters(ng);
- if (aps == null)
- continue;
- try {
- ngParams = aps.getParameterSpec(DHParameterSpec.class);
- } catch (InvalidParameterSpecException ipse) {
- // should be unlikely
- }
-
- if (ngParams == null) {
+ if (ng.spec != NamedGroupSpec.NAMED_GROUP_FFDHE) {
continue;
}
+ DHParameterSpec ngParams = (DHParameterSpec)ng.keAlgParamSpec;
if (ngParams.getP().equals(params.getP())
&& ngParams.getG().equals(params.getG())) {
return ng;
}
}
@@ -306,122 +356,132 @@
}
return "UNDEFINED-NAMED-GROUP(" + id + ")";
}
- // Are the NamedGroups available for the protocol desired?
-
+ // Is the NamedGroup available for the protocols desired?
boolean isAvailable(List<ProtocolVersion> protocolVersions) {
+ if (this.isAvailable) {
for (ProtocolVersion pv : supportedProtocols) {
if (protocolVersions.contains(pv)) {
return true;
}
}
+ }
+
return false;
}
boolean isAvailable(ProtocolVersion protocolVersion) {
+ if (this.isAvailable) {
for (ProtocolVersion pv : supportedProtocols) {
if (protocolVersion == pv) {
return true;
}
}
+ }
+
return false;
}
// Are the NamedGroups available for the ciphersuites desired?
-
boolean isSupported(List<CipherSuite> cipherSuites) {
for (CipherSuite cs : cipherSuites) {
boolean isMatch = isAvailable(cs.supportedProtocols);
if (isMatch && ((cs.keyExchange == null)
- || (NamedGroupType.arrayContains(
- cs.keyExchange.groupTypes, type)))) {
+ || (NamedGroupSpec.arrayContains(
+ cs.keyExchange.groupTypes, spec)))) {
return true;
}
}
+
return false;
}
- // lazy loading of parameters
- AlgorithmParameters getParameters() {
- Optional<NamedGroupFunctions> ngf = getFunctions();
- if (ngf.isEmpty()) {
- return null;
- }
- return ngf.get().getParameters(this);
- }
-
- // The next set of methods use the NamedGroupFunctions table
- // to do various operations in a consistent way.
-
- AlgorithmParameterSpec getParameterSpec() {
- Optional<NamedGroupFunctions> ngf = getFunctions();
- if (ngf.isEmpty()) {
- return null;
- }
- return ngf.get().getParameterSpec(this);
+ boolean isPermitted(AlgorithmConstraints constraints) {
+ return constraints.permits(KEY_AGREEMENT_PRIMITIVE_SET,
+ this.name, null) &&
+ constraints.permits(KEY_AGREEMENT_PRIMITIVE_SET,
+ this.algorithm, this.keAlgParams);
}
byte[] encodePossessionPublicKey(
NamedGroupPossession namedGroupPossession) {
-
- Optional<NamedGroupFunctions> ngf = getFunctions();
- if (ngf.isEmpty()) {
- return null;
- }
- return ngf.get().encodePossessionPublicKey(namedGroupPossession);
+ return spec.encodePossessionPublicKey(namedGroupPossession);
}
SSLCredentials decodeCredentials(byte[] encoded,
AlgorithmConstraints constraints,
ExceptionSupplier onConstraintFail)
throws IOException, GeneralSecurityException {
+ return spec.decodeCredentials(
+ this, encoded, constraints, onConstraintFail);
+ }
- Optional<NamedGroupFunctions> ngf = getFunctions();
- if (ngf.isEmpty()) {
- return null;
+ SSLPossession createPossession(SecureRandom random) {
+ return spec.createPossession(this, random);
}
- return ngf.get().decodeCredentials(this, encoded, constraints,
- onConstraintFail);
+
+ SSLKeyDerivation createKeyDerivation(
+ HandshakeContext hc) throws IOException {
+ return spec.createKeyDerivation(hc);
}
- SSLPossession createPossession(SecureRandom random) {
+ interface ExceptionSupplier {
+ void apply(String s) throws SSLException;
+ }
- Optional<NamedGroupFunctions> ngf = getFunctions();
- if (ngf.isEmpty()) {
- return null;
+ // A list of operations related to named groups.
+ private interface NamedGroupScheme {
+ default void checkConstraints(PublicKey publicKey,
+ AlgorithmConstraints constraints,
+ ExceptionSupplier onConstraintFail) throws SSLException {
+ if (!constraints.permits(
+ EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), publicKey)) {
+ onConstraintFail.apply("key share entry does not "
+ + "comply with algorithm constraints");
}
- return ngf.get().createPossession(this, random);
}
- SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
- throws IOException {
+ byte[] encodePossessionPublicKey(
+ NamedGroupPossession namedGroupPossession);
- Optional<NamedGroupFunctions> ngf = getFunctions();
- if (ngf.isEmpty()) {
- return null;
- }
- return ngf.get().createKeyDerivation(hc);
+ SSLCredentials decodeCredentials(
+ NamedGroup ng, byte[] encoded,
+ AlgorithmConstraints constraints,
+ ExceptionSupplier onConstraintFail
+ ) throws IOException, GeneralSecurityException;
- }
+ SSLPossession createPossession(NamedGroup ng, SecureRandom random);
- boolean isAvailableGroup() {
- Optional<NamedGroupFunctions> ngfOpt = getFunctions();
- if (ngfOpt.isEmpty()) {
- return false;
- }
- NamedGroupFunctions ngf = ngfOpt.get();
- return ngf.isAvailable(this);
+ SSLKeyDerivation createKeyDerivation(
+ HandshakeContext hc) throws IOException;
}
- enum NamedGroupType {
- NAMED_GROUP_ECDHE, // Elliptic Curve Groups (ECDHE)
- NAMED_GROUP_FFDHE, // Finite Field Groups (DHE)
- NAMED_GROUP_XDH, // Finite Field Groups (XDH)
- NAMED_GROUP_ARBITRARY, // arbitrary prime and curves (ECDHE)
- NAMED_GROUP_NONE; // Not predefined named group
+ enum NamedGroupSpec implements NamedGroupScheme {
+ // Elliptic Curve Groups (ECDHE)
+ NAMED_GROUP_ECDHE("EC", ECDHEScheme.instance),
+
+ // Finite Field Groups (DHE)
+ NAMED_GROUP_FFDHE("DiffieHellman", FFDHEScheme.instance),
+
+ // Finite Field Groups (XDH)
+ NAMED_GROUP_XDH("XDH", XDHScheme.instance),
+
+ // arbitrary prime and curves (ECDHE)
+ NAMED_GROUP_ARBITRARY("EC", null),
+
+ // Not predefined named group
+ NAMED_GROUP_NONE("", null);
+
+ private final String algorithm; // key exchange name
+ private final NamedGroupScheme scheme; // named group operations
+
+ private NamedGroupSpec(String algorithm, NamedGroupScheme scheme) {
+ this.algorithm = algorithm;
+ this.scheme = scheme;
+ }
boolean isSupported(List<CipherSuite> cipherSuites) {
for (CipherSuite cs : cipherSuites) {
if (cs.keyExchange == null ||
arrayContains(cs.keyExchange.groupTypes, this)) {
@@ -430,108 +490,79 @@
}
return false;
}
- static boolean arrayContains(NamedGroupType[] namedGroupTypes,
- NamedGroupType namedGroupType) {
- for (NamedGroupType ng : namedGroupTypes) {
+ static boolean arrayContains(NamedGroupSpec[] namedGroupTypes,
+ NamedGroupSpec namedGroupType) {
+ for (NamedGroupSpec ng : namedGroupTypes) {
if (ng == namedGroupType) {
return true;
}
}
+
return false;
}
- }
- interface ExceptionSupplier {
- void apply(String s) throws SSLException;
+ @Override
+ public byte[] encodePossessionPublicKey(
+ NamedGroupPossession namedGroupPossession) {
+ if (scheme != null) {
+ return scheme.encodePossessionPublicKey(namedGroupPossession);
}
- /*
- * A list of functions to do NamedGroup operations in a
- * algorithm-independent and consistent way.
- */
- private static abstract class NamedGroupFunctions {
-
- // cache to speed up the parameters construction
- protected static final Map<NamedGroup, AlgorithmParameters>
- namedGroupParams = new ConcurrentHashMap<>();
+ return null;
+ }
- protected void checkConstraints(PublicKey publicKey,
+ @Override
+ public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
AlgorithmConstraints constraints,
- ExceptionSupplier onConstraintFail)
- throws SSLException {
-
- if (!constraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- publicKey)) {
-
- onConstraintFail.apply("key share entry does not "
- + "comply with algorithm constraints");
- }
+ ExceptionSupplier onConstraintFail
+ ) throws IOException, GeneralSecurityException {
+ if (scheme != null) {
+ return scheme.decodeCredentials(
+ ng, encoded, constraints, onConstraintFail);
}
- public AlgorithmParameters getParameters(NamedGroup ng) {
-
- AlgorithmParameters result = namedGroupParams.get(ng);
- if (result == null) {
- Optional<AlgorithmParameters> paramsOpt = getParametersImpl(ng);
- if (paramsOpt.isPresent()) {
- result = paramsOpt.get();
- namedGroupParams.put(ng, result);
- }
+ return null;
}
- return result;
+ @Override
+ public SSLPossession createPossession(
+ NamedGroup ng, SecureRandom random) {
+ if (scheme != null) {
+ return scheme.createPossession(ng, random);
}
- public abstract byte[] encodePossessionPublicKey(
- NamedGroupPossession namedGroupPossession);
-
- public abstract SSLCredentials decodeCredentials(
- NamedGroup ng, byte[] encoded,
- AlgorithmConstraints constraints,
- ExceptionSupplier onConstraintFail)
- throws IOException, GeneralSecurityException;
-
- public abstract SSLPossession createPossession(NamedGroup ng,
- SecureRandom random);
-
- public abstract SSLKeyDerivation createKeyDerivation(
- HandshakeContext hc) throws IOException;
-
- protected abstract Optional<AlgorithmParameters> getParametersImpl(
- NamedGroup ng);
-
- public abstract AlgorithmParameterSpec getParameterSpec(NamedGroup ng);
-
- public abstract boolean isAvailable(NamedGroup ng);
+ return null;
}
- private static class FFDHFunctions extends NamedGroupFunctions {
-
- // lazy initialization
- private static class FunctionsHolder {
- private static final FFDHFunctions instance = new FFDHFunctions();
+ @Override
+ public SSLKeyDerivation createKeyDerivation(
+ HandshakeContext hc) throws IOException {
+ if (scheme != null) {
+ return scheme.createKeyDerivation(hc);
}
- private static FFDHFunctions getInstance() {
- return FunctionsHolder.instance;
+ return null;
+ }
}
+ private static class FFDHEScheme implements NamedGroupScheme {
+ private static final FFDHEScheme instance = new FFDHEScheme();
+
@Override
public byte[] encodePossessionPublicKey(
NamedGroupPossession namedGroupPossession) {
return ((DHEPossession)namedGroupPossession).encode();
}
@Override
public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
AlgorithmConstraints constraints,
- ExceptionSupplier onConstraintFail)
- throws IOException, GeneralSecurityException {
+ ExceptionSupplier onConstraintFail
+ ) throws IOException, GeneralSecurityException {
DHKeyExchange.DHECredentials result
= DHKeyExchange.DHECredentials.valueOf(ng, encoded);
checkConstraints(result.getPublicKey(), constraints,
@@ -545,127 +576,31 @@
NamedGroup ng, SecureRandom random) {
return new DHKeyExchange.DHEPossession(ng, random);
}
@Override
- public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
- throws IOException {
+ public SSLKeyDerivation createKeyDerivation(
+ HandshakeContext hc) throws IOException {
return DHKeyExchange.kaGenerator.createKeyDerivation(hc);
}
-
- @Override
- public AlgorithmParameterSpec getParameterSpec(NamedGroup ng) {
- return getDHParameterSpec(ng);
- }
-
- DHParameterSpec getDHParameterSpec(NamedGroup ng) {
-
- AlgorithmParameters params = getParameters(ng);
- try {
- return params.getParameterSpec(DHParameterSpec.class);
- } catch (InvalidParameterSpecException ipse) {
- // should be unlikely
- return getPredefinedDHParameterSpec(ng);
- }
- }
-
- private static DHParameterSpec getFFDHEDHParameterSpec(
- NamedGroup namedGroup) {
-
- DHParameterSpec spec = null;
- switch (namedGroup) {
- case FFDHE_2048:
- spec = PredefinedDHParameterSpecs.ffdheParams.get(2048);
- break;
- case FFDHE_3072:
- spec = PredefinedDHParameterSpecs.ffdheParams.get(3072);
- break;
- case FFDHE_4096:
- spec = PredefinedDHParameterSpecs.ffdheParams.get(4096);
- break;
- case FFDHE_6144:
- spec = PredefinedDHParameterSpecs.ffdheParams.get(6144);
- break;
- case FFDHE_8192:
- spec = PredefinedDHParameterSpecs.ffdheParams.get(8192);
- }
-
- return spec;
}
- private static DHParameterSpec getPredefinedDHParameterSpec(
- NamedGroup namedGroup) {
-
- DHParameterSpec spec = null;
- switch (namedGroup) {
- case FFDHE_2048:
- spec = PredefinedDHParameterSpecs.definedParams.get(2048);
- break;
- case FFDHE_3072:
- spec = PredefinedDHParameterSpecs.definedParams.get(3072);
- break;
- case FFDHE_4096:
- spec = PredefinedDHParameterSpecs.definedParams.get(4096);
- break;
- case FFDHE_6144:
- spec = PredefinedDHParameterSpecs.definedParams.get(6144);
- break;
- case FFDHE_8192:
- spec = PredefinedDHParameterSpecs.definedParams.get(8192);
- }
-
- return spec;
- }
-
- @Override
- public boolean isAvailable(NamedGroup ng) {
-
- AlgorithmParameters params = getParameters(ng);
- return params != null;
- }
-
- @Override
- protected Optional<AlgorithmParameters> getParametersImpl(
- NamedGroup ng) {
- try {
- AlgorithmParameters params
- = JsseJce.getAlgorithmParameters("DiffieHellman");
- AlgorithmParameterSpec spec
- = getFFDHEDHParameterSpec(ng);
- params.init(spec);
- return Optional.of(params);
- } catch (InvalidParameterSpecException
- | NoSuchAlgorithmException ex) {
- return Optional.empty();
- }
- }
-
- }
-
- private static class ECDHFunctions extends NamedGroupFunctions {
-
- // lazy initialization
- private static class FunctionsHolder {
- private static final ECDHFunctions instance = new ECDHFunctions();
- }
-
- private static ECDHFunctions getInstance() {
- return FunctionsHolder.instance;
- }
+ private static class ECDHEScheme implements NamedGroupScheme {
+ private static final ECDHEScheme instance = new ECDHEScheme();
@Override
public byte[] encodePossessionPublicKey(
NamedGroupPossession namedGroupPossession) {
return ((ECDHEPossession)namedGroupPossession).encode();
}
@Override
public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
AlgorithmConstraints constraints,
- ExceptionSupplier onConstraintFail)
- throws IOException, GeneralSecurityException {
+ ExceptionSupplier onConstraintFail
+ ) throws IOException, GeneralSecurityException {
ECDHKeyExchange.ECDHECredentials result
= ECDHKeyExchange.ECDHECredentials.valueOf(ng, encoded);
checkConstraints(result.getPublicKey(), constraints,
@@ -679,67 +614,29 @@
NamedGroup ng, SecureRandom random) {
return new ECDHKeyExchange.ECDHEPossession(ng, random);
}
@Override
- public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
- throws IOException {
-
+ public SSLKeyDerivation createKeyDerivation(
+ HandshakeContext hc) throws IOException {
return ECDHKeyExchange.ecdheKAGenerator.createKeyDerivation(hc);
}
-
- @Override
- public AlgorithmParameterSpec getParameterSpec(NamedGroup ng) {
- return SupportedGroupsExtension.SupportedGroups
- .getECGenParamSpec(ng);
- }
-
- @Override
- public boolean isAvailable(NamedGroup ng) {
-
- AlgorithmParameters params = getParameters(ng);
- return params != null;
- }
-
- @Override
- protected Optional<AlgorithmParameters> getParametersImpl(
- NamedGroup ng) {
- try {
- AlgorithmParameters params
- = JsseJce.getAlgorithmParameters("EC");
- AlgorithmParameterSpec spec
- = new ECGenParameterSpec(ng.oid);
- params.init(spec);
- return Optional.of(params);
- } catch (InvalidParameterSpecException
- | NoSuchAlgorithmException ex) {
- return Optional.empty();
- }
- }
- }
-
- private static class XDHFunctions extends NamedGroupFunctions {
-
- // lazy initialization
- private static class FunctionsHolder {
- private static final XDHFunctions instance = new XDHFunctions();
}
- private static XDHFunctions getInstance() {
- return FunctionsHolder.instance;
- }
+ private static class XDHScheme implements NamedGroupScheme {
+ private static final XDHScheme instance = new XDHScheme();
@Override
public byte[] encodePossessionPublicKey(NamedGroupPossession poss) {
return ((XDHKeyExchange.XDHEPossession)poss).encode();
}
@Override
public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
AlgorithmConstraints constraints,
- ExceptionSupplier onConstraintFail)
- throws IOException, GeneralSecurityException {
+ ExceptionSupplier onConstraintFail
+ ) throws IOException, GeneralSecurityException {
XDHKeyExchange.XDHECredentials result
= XDHKeyExchange.XDHECredentials.valueOf(ng, encoded);
checkConstraints(result.getPublicKey(), constraints,
@@ -753,33 +650,11 @@
NamedGroup ng, SecureRandom random) {
return new XDHKeyExchange.XDHEPossession(ng, random);
}
@Override
- public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
- throws IOException {
+ public SSLKeyDerivation createKeyDerivation(
+ HandshakeContext hc) throws IOException {
return XDHKeyExchange.xdheKAGenerator.createKeyDerivation(hc);
}
-
- @Override
- public AlgorithmParameterSpec getParameterSpec(NamedGroup ng) {
- return new NamedParameterSpec(ng.name);
- }
-
- @Override
- public boolean isAvailable(NamedGroup ng) {
-
- try {
- JsseJce.getKeyAgreement(ng.algorithm);
- return true;
- } catch (NoSuchAlgorithmException ex) {
- return false;
- }
- }
-
- @Override
- protected Optional<AlgorithmParameters> getParametersImpl(
- NamedGroup ng) {
- return Optional.empty();
- }
}
}
< prev index next >