8140436: Negotiated Finite Field Diffie-Hellman Ephemeral Parameters for TLS
Reviewed-by: valeriep, jnimeh, apetcher
--- a/jdk/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Thu May 11 07:33:23 2017 +0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Wed May 10 23:40:46 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,7 @@
import static sun.security.ssl.CipherSuite.MacAlg.*;
import static sun.security.ssl.CipherSuite.BulkCipher.*;
import static sun.security.ssl.JsseJce.*;
+import static sun.security.ssl.NamedGroupType.*;
/**
* An SSL/TLS CipherSuite. Constants for the standard key exchange, cipher,
@@ -376,38 +377,38 @@
static enum KeyExchange {
// key exchange algorithms
- K_NULL ("NULL", false, false),
- K_RSA ("RSA", true, false),
- K_RSA_EXPORT ("RSA_EXPORT", true, false),
- K_DH_RSA ("DH_RSA", false, false),
- K_DH_DSS ("DH_DSS", false, false),
- K_DHE_DSS ("DHE_DSS", true, false),
- K_DHE_RSA ("DHE_RSA", true, false),
- K_DH_ANON ("DH_anon", true, false),
+ K_NULL ("NULL", false, NAMED_GROUP_NONE),
+ K_RSA ("RSA", true, NAMED_GROUP_NONE),
+ K_RSA_EXPORT ("RSA_EXPORT", true, NAMED_GROUP_NONE),
+ K_DH_RSA ("DH_RSA", false, NAMED_GROUP_NONE),
+ K_DH_DSS ("DH_DSS", false, NAMED_GROUP_NONE),
+ K_DHE_DSS ("DHE_DSS", true, NAMED_GROUP_FFDHE),
+ K_DHE_RSA ("DHE_RSA", true, NAMED_GROUP_FFDHE),
+ K_DH_ANON ("DH_anon", true, NAMED_GROUP_FFDHE),
- K_ECDH_ECDSA ("ECDH_ECDSA", ALLOW_ECC, true),
- K_ECDH_RSA ("ECDH_RSA", ALLOW_ECC, true),
- K_ECDHE_ECDSA("ECDHE_ECDSA", ALLOW_ECC, true),
- K_ECDHE_RSA ("ECDHE_RSA", ALLOW_ECC, true),
- K_ECDH_ANON ("ECDH_anon", ALLOW_ECC, true),
+ K_ECDH_ECDSA ("ECDH_ECDSA", ALLOW_ECC, NAMED_GROUP_ECDHE),
+ K_ECDH_RSA ("ECDH_RSA", ALLOW_ECC, NAMED_GROUP_ECDHE),
+ K_ECDHE_ECDSA("ECDHE_ECDSA", ALLOW_ECC, NAMED_GROUP_ECDHE),
+ K_ECDHE_RSA ("ECDHE_RSA", ALLOW_ECC, NAMED_GROUP_ECDHE),
+ K_ECDH_ANON ("ECDH_anon", ALLOW_ECC, NAMED_GROUP_ECDHE),
// Kerberos cipher suites
- K_KRB5 ("KRB5", true, false),
- K_KRB5_EXPORT("KRB5_EXPORT", true, false),
+ K_KRB5 ("KRB5", true, NAMED_GROUP_NONE),
+ K_KRB5_EXPORT("KRB5_EXPORT", true, NAMED_GROUP_NONE),
// renegotiation protection request signaling cipher suite
- K_SCSV ("SCSV", true, false);
+ K_SCSV ("SCSV", true, NAMED_GROUP_NONE);
// name of the key exchange algorithm, e.g. DHE_DSS
final String name;
final boolean allowed;
- final boolean isEC;
+ final NamedGroupType groupType;
private final boolean alwaysAvailable;
- KeyExchange(String name, boolean allowed, boolean isEC) {
+ KeyExchange(String name, boolean allowed, NamedGroupType groupType) {
this.name = name;
this.allowed = allowed;
- this.isEC = isEC;
+ this.groupType = groupType;
this.alwaysAvailable = allowed &&
(!name.startsWith("EC")) && (!name.startsWith("KRB"));
}
@@ -417,7 +418,7 @@
return true;
}
- if (isEC) {
+ if (groupType == NAMED_GROUP_ECDHE) {
return (allowed && JsseJce.isEcAvailable());
} else if (name.startsWith("KRB")) {
return (allowed && JsseJce.isKerberosAvailable());
--- a/jdk/src/java.base/share/classes/sun/security/ssl/CipherSuiteList.java Thu May 11 07:33:23 2017 +0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/CipherSuiteList.java Wed May 10 23:40:46 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
import java.util.*;
import javax.net.ssl.SSLException;
+import static sun.security.ssl.NamedGroupType.*;
/**
* A list of CipherSuites. Also maintains the lists of supported and
@@ -42,15 +43,16 @@
private final Collection<CipherSuite> cipherSuites;
private String[] suiteNames;
-
- // flag indicating whether this list contains any ECC ciphersuites.
- // null if not yet checked.
- private volatile Boolean containsEC;
+ private final EnumSet<NamedGroupType> groupsTypes =
+ EnumSet.noneOf(NamedGroupType.class);
// for use by buildAvailableCache() and
// Handshaker.getKickstartMessage() only
CipherSuiteList(Collection<CipherSuite> cipherSuites) {
this.cipherSuites = cipherSuites;
+ for (CipherSuite suite : cipherSuites) {
+ updateGroupTypes(suite);
+ }
}
/**
@@ -59,6 +61,7 @@
CipherSuiteList(CipherSuite suite) {
cipherSuites = new ArrayList<CipherSuite>(1);
cipherSuites.add(suite);
+ updateGroupTypes(suite);
}
/**
@@ -82,6 +85,7 @@
+ suiteName + " with currently installed providers");
}
cipherSuites.add(suite);
+ updateGroupTypes(suite);
}
}
@@ -97,7 +101,20 @@
}
cipherSuites = new ArrayList<CipherSuite>(bytes.length >> 1);
for (int i = 0; i < bytes.length; i += 2) {
- cipherSuites.add(CipherSuite.valueOf(bytes[i], bytes[i+1]));
+ CipherSuite suite = CipherSuite.valueOf(bytes[i], bytes[i+1]);
+ cipherSuites.add(suite);
+ updateGroupTypes(suite);
+ }
+ }
+
+ // Please don't use this method except constructors.
+ private void updateGroupTypes(CipherSuite cipherSuite) {
+ if (cipherSuite.keyExchange != null && (!cipherSuite.exportable)) {
+ NamedGroupType groupType = cipherSuite.keyExchange.groupType;
+ if ((groupType != NAMED_GROUP_NONE) &&
+ (!groupsTypes.contains(groupType))) {
+ groupsTypes.add(groupType);
+ }
}
}
@@ -108,20 +125,9 @@
return cipherSuites.contains(suite);
}
- // Return whether this list contains any ECC ciphersuites
- boolean containsEC() {
- if (containsEC == null) {
- for (CipherSuite c : cipherSuites) {
- if (c.keyExchange.isEC) {
- containsEC = true;
- return true;
- }
- }
-
- containsEC = false;
- }
-
- return containsEC;
+ // Return whether this list contains cipher suites of a named group type.
+ boolean contains(NamedGroupType groupType) {
+ return groupsTypes.contains(groupType);
}
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java Thu May 11 07:33:23 2017 +0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java Wed May 10 23:40:46 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -148,6 +148,10 @@
private static final boolean enableMFLExtension =
Debug.getBooleanProperty("jsse.enableMFLExtension", false);
+ // To switch off the supported_groups extension for DHE cipher suite.
+ private static final boolean enableFFDHE =
+ Debug.getBooleanProperty("jsse.enableFFDHE", true);
+
// Whether an ALPN extension was sent in the ClientHello
private boolean alpnActive = false;
@@ -767,13 +771,15 @@
fatalSE(Alerts.alert_unexpected_message, "Server set " +
type + " extension when not requested by client");
}
- } else if ((type != ExtensionType.EXT_ELLIPTIC_CURVES)
+ } else if ((type != ExtensionType.EXT_SUPPORTED_GROUPS)
&& (type != ExtensionType.EXT_EC_POINT_FORMATS)
&& (type != ExtensionType.EXT_SERVER_NAME)
&& (type != ExtensionType.EXT_ALPN)
&& (type != ExtensionType.EXT_RENEGOTIATION_INFO)
&& (type != ExtensionType.EXT_STATUS_REQUEST)
&& (type != ExtensionType.EXT_STATUS_REQUEST_V2)) {
+ // Note: Better to check client requested extensions rather
+ // than all supported extensions.
fatalSE(Alerts.alert_unsupported_extension,
"Server sent an unsupported extension: " + type);
}
@@ -823,6 +829,17 @@
* our own D-H algorithm object so we can defer key calculations
* until after we've sent the client key exchange message (which
* gives client and server some useful parallelism).
+ *
+ * Note per section 3 of RFC 7919, if the server is not compatible with
+ * FFDHE specification, the client MAY decide to continue the connection
+ * if the selected DHE group is acceptable under local policy, or it MAY
+ * decide to terminate the connection with a fatal insufficient_security
+ * (71) alert. The algorithm constraints mechanism is JDK local policy
+ * used for additional DHE parameters checking. So this implementation
+ * does not check the server compatibility and just pass to the local
+ * algorithm constraints checking. The client will continue the
+ * connection if the server selected DHE group is acceptable by the
+ * specified algorithm constraints.
*/
private void serverKeyExchange(DH_ServerKeyExchange mesg)
throws IOException {
@@ -1495,14 +1512,17 @@
sslContext.getSecureRandom(), maxProtocolVersion,
sessionId, cipherSuites, isDTLS);
- // add elliptic curves and point format extensions
- if (cipherSuites.containsEC()) {
- EllipticCurvesExtension ece =
- EllipticCurvesExtension.createExtension(algorithmConstraints);
- if (ece != null) {
- clientHelloMessage.extensions.add(ece);
+ // Add named groups extension for ECDHE and FFDHE if necessary.
+ SupportedGroupsExtension sge =
+ SupportedGroupsExtension.createExtension(
+ algorithmConstraints,
+ cipherSuites, enableFFDHE);
+ if (sge != null) {
+ clientHelloMessage.extensions.add(sge);
+ // Add elliptic point format extensions
+ if (cipherSuites.contains(NamedGroupType.NAMED_GROUP_ECDHE)) {
clientHelloMessage.extensions.add(
- EllipticPointFormatsExtension.DEFAULT);
+ EllipticPointFormatsExtension.DEFAULT);
}
}
--- a/jdk/src/java.base/share/classes/sun/security/ssl/DHCrypt.java Thu May 11 07:33:23 2017 +0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/DHCrypt.java Wed May 10 23:40:46 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,14 +26,8 @@
package sun.security.ssl;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Collections;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
import java.math.BigInteger;
import java.security.*;
-import java.io.IOException;
import javax.net.ssl.SSLHandshakeException;
import javax.crypto.SecretKey;
import javax.crypto.KeyAgreement;
@@ -101,7 +95,7 @@
*/
DHCrypt(int keyLength, SecureRandom random) {
this(keyLength,
- ParametersHolder.definedParams.get(keyLength), random);
+ PredefinedDHParameterSpecs.definedParams.get(keyLength), random);
}
/**
@@ -116,6 +110,14 @@
}
/**
+ * Generate a Diffie-Hellman keypair using the named group.
+ */
+ DHCrypt(NamedGroup namedGroup, SecureRandom random) {
+ this(-1, // The length (-1) is not used in the implementation.
+ SupportedGroupsExtension.getDHParameterSpec(namedGroup), random);
+ }
+
+ /**
* Generate a Diffie-Hellman keypair using the specified size and
* parameters.
*/
@@ -272,266 +274,5 @@
return null;
}
-
- // lazy initialization holder class idiom for static default parameters
- //
- // See Effective Java Second Edition: Item 71.
- private static class ParametersHolder {
- private final static boolean debugIsOn =
- (Debug.getInstance("ssl") != null) && Debug.isOn("sslctx");
-
- //
- // Default DH ephemeral parameters
- //
- private static final BigInteger p512 = new BigInteger( // generated
- "D87780E15FF50B4ABBE89870188B049406B5BEA98AB23A02" +
- "41D88EA75B7755E669C08093D3F0CA7FC3A5A25CF067DCB9" +
- "A43DD89D1D90921C6328884461E0B6D3", 16);
- private static final BigInteger p768 = new BigInteger( // RFC 2409
- "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
- "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
- "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
- "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF", 16);
+}
- private static final BigInteger p1024 = new BigInteger( // RFC 2409
- "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
- "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
- "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
- "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
- "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" +
- "FFFFFFFFFFFFFFFF", 16);
- private static final BigInteger p1536 = new BigInteger( // RFC 3526
- "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
- "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
- "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
- "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
- "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" +
- "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +
- "83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
- "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 16);
- private static final BigInteger p2048 = new BigInteger( // TLS FFDHE
- "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
- "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
- "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
- "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
- "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
- "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
- "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
- "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
- "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
- "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
- "886B423861285C97FFFFFFFFFFFFFFFF", 16);
- private static final BigInteger p3072 = new BigInteger( // TLS FFDHE
- "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
- "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
- "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
- "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
- "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
- "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
- "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
- "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
- "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
- "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
- "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
- "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
- "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
- "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
- "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
- "3C1B20EE3FD59D7C25E41D2B66C62E37FFFFFFFFFFFFFFFF", 16);
- private static final BigInteger p4096 = new BigInteger( // TLS FFDHE
- "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
- "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
- "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
- "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
- "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
- "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
- "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
- "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
- "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
- "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
- "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
- "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
- "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
- "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
- "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
- "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" +
- "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004" +
- "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" +
- "A907600A918130C46DC778F971AD0038092999A333CB8B7A" +
- "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" +
- "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E655F6A" +
- "FFFFFFFFFFFFFFFF", 16);
- private static final BigInteger p6144 = new BigInteger( // TLS FFDHE
- "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
- "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
- "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
- "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
- "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
- "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
- "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
- "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
- "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
- "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
- "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
- "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
- "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
- "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
- "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
- "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" +
- "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004" +
- "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" +
- "A907600A918130C46DC778F971AD0038092999A333CB8B7A" +
- "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" +
- "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD902" +
- "0BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA6" +
- "3BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3A" +
- "CDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477" +
- "A52471F7A9A96910B855322EDB6340D8A00EF092350511E3" +
- "0ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4" +
- "763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6" +
- "B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538C" +
- "D72B03746AE77F5E62292C311562A846505DC82DB854338A" +
- "E49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B04" +
- "5B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1" +
- "A41D570D7938DAD4A40E329CD0E40E65FFFFFFFFFFFFFFFF", 16);
- private static final BigInteger p8192 = new BigInteger( // TLS FFDHE
- "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
- "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
- "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
- "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
- "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
- "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
- "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
- "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
- "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
- "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
- "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
- "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
- "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
- "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
- "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
- "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" +
- "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004" +
- "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" +
- "A907600A918130C46DC778F971AD0038092999A333CB8B7A" +
- "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" +
- "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD902" +
- "0BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA6" +
- "3BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3A" +
- "CDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477" +
- "A52471F7A9A96910B855322EDB6340D8A00EF092350511E3" +
- "0ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4" +
- "763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6" +
- "B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538C" +
- "D72B03746AE77F5E62292C311562A846505DC82DB854338A" +
- "E49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B04" +
- "5B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1" +
- "A41D570D7938DAD4A40E329CCFF46AAA36AD004CF600C838" +
- "1E425A31D951AE64FDB23FCEC9509D43687FEB69EDD1CC5E" +
- "0B8CC3BDF64B10EF86B63142A3AB8829555B2F747C932665" +
- "CB2C0F1CC01BD70229388839D2AF05E454504AC78B758282" +
- "2846C0BA35C35F5C59160CC046FD8251541FC68C9C86B022" +
- "BB7099876A460E7451A8A93109703FEE1C217E6C3826E52C" +
- "51AA691E0E423CFC99E9E31650C1217B624816CDAD9A95F9" +
- "D5B8019488D9C0A0A1FE3075A577E23183F81D4A3F2FA457" +
- "1EFC8CE0BA8A4FE8B6855DFE72B0A66EDED2FBABFBE58A30" +
- "FAFABE1C5D71A87E2F741EF8C1FE86FEA6BBFDE530677F0D" +
- "97D11D49F7A8443D0822E506A9F4614E011E2A94838FF88C" +
- "D68C8BB7C5C6424CFFFFFFFFFFFFFFFF", 16);
-
- private static final BigInteger[] supportedPrimes = {
- p512, p768, p1024, p1536, p2048, p3072, p4096, p6144, p8192};
-
- // a measure of the uncertainty that prime modulus p is not a prime
- //
- // see BigInteger.isProbablePrime(int certainty)
- private final static int PRIME_CERTAINTY = 120;
-
- // the known security property, jdk.tls.server.defaultDHEParameters
- private final static String PROPERTY_NAME =
- "jdk.tls.server.defaultDHEParameters";
-
- private static final Pattern spacesPattern = Pattern.compile("\\s+");
-
- private final static Pattern syntaxPattern = Pattern.compile(
- "(\\{[0-9A-Fa-f]+,[0-9A-Fa-f]+\\})" +
- "(,\\{[0-9A-Fa-f]+,[0-9A-Fa-f]+\\})*");
-
- private static final Pattern paramsPattern = Pattern.compile(
- "\\{([0-9A-Fa-f]+),([0-9A-Fa-f]+)\\}");
-
- // cache of predefined default DH ephemeral parameters
- private final static Map<Integer,DHParameterSpec> definedParams;
-
- static {
- String property = AccessController.doPrivileged(
- new PrivilegedAction<String>() {
- public String run() {
- return Security.getProperty(PROPERTY_NAME);
- }
- });
-
- if (property != null && !property.isEmpty()) {
- // remove double quote marks from beginning/end of the property
- if (property.length() >= 2 && property.charAt(0) == '"' &&
- property.charAt(property.length() - 1) == '"') {
- property = property.substring(1, property.length() - 1);
- }
-
- property = property.trim();
- }
-
- if (property != null && !property.isEmpty()) {
- Matcher spacesMatcher = spacesPattern.matcher(property);
- property = spacesMatcher.replaceAll("");
-
- if (debugIsOn) {
- System.out.println("The Security Property " +
- PROPERTY_NAME + ": " + property);
- }
- }
-
- Map<Integer,DHParameterSpec> defaultParams = new HashMap<>();
- if (property != null && !property.isEmpty()) {
- Matcher syntaxMatcher = syntaxPattern.matcher(property);
- if (syntaxMatcher.matches()) {
- Matcher paramsFinder = paramsPattern.matcher(property);
- while(paramsFinder.find()) {
- String primeModulus = paramsFinder.group(1);
- BigInteger p = new BigInteger(primeModulus, 16);
- if (!p.isProbablePrime(PRIME_CERTAINTY)) {
- if (debugIsOn) {
- System.out.println(
- "Prime modulus p in Security Property, " +
- PROPERTY_NAME + ", is not a prime: " +
- primeModulus);
- }
-
- continue;
- }
-
- String baseGenerator = paramsFinder.group(2);
- BigInteger g = new BigInteger(baseGenerator, 16);
-
- DHParameterSpec spec = new DHParameterSpec(p, g);
- int primeLen = p.bitLength();
- defaultParams.put(primeLen, spec);
- }
- } else if (debugIsOn) {
- System.out.println("Invalid Security Property, " +
- PROPERTY_NAME + ", definition");
- }
- }
-
- for (BigInteger p : supportedPrimes) {
- int primeLen = p.bitLength();
- defaultParams.putIfAbsent(primeLen,
- new DHParameterSpec(p, BigInteger.TWO));
- }
-
- definedParams =
- Collections.<Integer,DHParameterSpec>unmodifiableMap(
- defaultParams);
- }
- }
-}
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ECDHCrypt.java Thu May 11 07:33:23 2017 +0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ECDHCrypt.java Wed May 10 23:40:46 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -56,17 +56,17 @@
}
// Called by ServerHandshaker for ephemeral ECDH
- ECDHCrypt(int curveId, SecureRandom random) {
+ ECDHCrypt(NamedGroup namedGroup, SecureRandom random) {
try {
KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
ECGenParameterSpec params =
- EllipticCurvesExtension.getECGenParamSpec(curveId);
+ SupportedGroupsExtension.getECGenParamSpec(namedGroup);
kpg.initialize(params, random);
KeyPair kp = kpg.generateKeyPair();
privateKey = kp.getPrivate();
publicKey = (ECPublicKey)kp.getPublic();
} catch (GeneralSecurityException e) {
- throw new RuntimeException("Could not generate DH keypair", e);
+ throw new RuntimeException("Could not generate ECDH keypair", e);
}
}
@@ -79,7 +79,7 @@
privateKey = kp.getPrivate();
publicKey = (ECPublicKey)kp.getPublic();
} catch (GeneralSecurityException e) {
- throw new RuntimeException("Could not generate DH keypair", e);
+ throw new RuntimeException("Could not generate ECDH keypair", e);
}
}
--- a/jdk/src/java.base/share/classes/sun/security/ssl/EllipticCurvesExtension.java Thu May 11 07:33:23 2017 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,400 +0,0 @@
-/*
- * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.IOException;
-import java.security.spec.ECParameterSpec;
-import java.security.spec.ECGenParameterSpec;
-import java.security.spec.InvalidParameterSpecException;
-import java.security.AlgorithmParameters;
-import java.security.AlgorithmConstraints;
-import java.security.CryptoPrimitive;
-import java.security.AccessController;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.ArrayList;
-import javax.net.ssl.SSLProtocolException;
-
-import sun.security.action.GetPropertyAction;
-
-final class EllipticCurvesExtension extends HelloExtension {
-
- /* Class and subclass dynamic debugging support */
- private static final Debug debug = Debug.getInstance("ssl");
-
- private static final int ARBITRARY_PRIME = 0xff01;
- private static final int ARBITRARY_CHAR2 = 0xff02;
-
- // speed up the searching
- private static final Map<String, Integer> oidToIdMap = new HashMap<>();
- private static final Map<Integer, String> idToOidMap = new HashMap<>();
-
- // speed up the parameters construction
- private static final Map<Integer,
- AlgorithmParameters> idToParams = new HashMap<>();
-
- // the supported elliptic curves
- private static final int[] supportedCurveIds;
-
- // the curves of the extension
- private final int[] curveIds;
-
- // See sun.security.util.CurveDB for the OIDs
- private static enum NamedEllipticCurve {
- T163_K1(1, "sect163k1", "1.3.132.0.1", true), // NIST K-163
- T163_R1(2, "sect163r1", "1.3.132.0.2", false),
- T163_R2(3, "sect163r2", "1.3.132.0.15", true), // NIST B-163
- T193_R1(4, "sect193r1", "1.3.132.0.24", false),
- T193_R2(5, "sect193r2", "1.3.132.0.25", false),
- T233_K1(6, "sect233k1", "1.3.132.0.26", true), // NIST K-233
- T233_R1(7, "sect233r1", "1.3.132.0.27", true), // NIST B-233
- T239_K1(8, "sect239k1", "1.3.132.0.3", false),
- T283_K1(9, "sect283k1", "1.3.132.0.16", true), // NIST K-283
- T283_R1(10, "sect283r1", "1.3.132.0.17", true), // NIST B-283
- T409_K1(11, "sect409k1", "1.3.132.0.36", true), // NIST K-409
- T409_R1(12, "sect409r1", "1.3.132.0.37", true), // NIST B-409
- T571_K1(13, "sect571k1", "1.3.132.0.38", true), // NIST K-571
- T571_R1(14, "sect571r1", "1.3.132.0.39", true), // NIST B-571
-
- P160_K1(15, "secp160k1", "1.3.132.0.9", false),
- P160_R1(16, "secp160r1", "1.3.132.0.8", false),
- P160_R2(17, "secp160r2", "1.3.132.0.30", false),
- P192_K1(18, "secp192k1", "1.3.132.0.31", false),
- P192_R1(19, "secp192r1", "1.2.840.10045.3.1.1", true), // NIST P-192
- P224_K1(20, "secp224k1", "1.3.132.0.32", false),
- P224_R1(21, "secp224r1", "1.3.132.0.33", true), // NIST P-224
- P256_K1(22, "secp256k1", "1.3.132.0.10", false),
- P256_R1(23, "secp256r1", "1.2.840.10045.3.1.7", true), // NIST P-256
- P384_R1(24, "secp384r1", "1.3.132.0.34", true), // NIST P-384
- P521_R1(25, "secp521r1", "1.3.132.0.35", true); // NIST P-521
-
- int id;
- String name;
- String oid;
- boolean isFips;
-
- NamedEllipticCurve(int id, String name, String oid, boolean isFips) {
- this.id = id;
- this.name = name;
- this.oid = oid;
- this.isFips = isFips;
-
- if (oidToIdMap.put(oid, id) != null ||
- idToOidMap.put(id, oid) != null) {
-
- throw new RuntimeException(
- "Duplicate named elliptic curve definition: " + name);
- }
- }
-
- static NamedEllipticCurve getCurve(String name, boolean requireFips) {
- for (NamedEllipticCurve curve : NamedEllipticCurve.values()) {
- if (curve.name.equals(name) && (!requireFips || curve.isFips)) {
- return curve;
- }
- }
-
- return null;
- }
- }
-
- static {
- boolean requireFips = SunJSSE.isFIPS();
-
- // hack code to initialize NamedEllipticCurve
- NamedEllipticCurve nec =
- NamedEllipticCurve.getCurve("secp256r1", false);
-
- // The value of the System Property defines a list of enabled named
- // curves in preference order, separated with comma. For example:
- //
- // jdk.tls.namedGroups="secp521r1, secp256r1, secp384r1"
- //
- // If the System Property is not defined or the value is empty, the
- // default curves and preferences will be used.
- String property = AccessController.doPrivileged(
- new GetPropertyAction("jdk.tls.namedGroups"));
- if (property != null && property.length() != 0) {
- // remove double quote marks from beginning/end of the property
- if (property.length() > 1 && property.charAt(0) == '"' &&
- property.charAt(property.length() - 1) == '"') {
- property = property.substring(1, property.length() - 1);
- }
- }
-
- ArrayList<Integer> idList;
- if (property != null && property.length() != 0) { // customized curves
- String[] curves = property.split(",");
- idList = new ArrayList<>(curves.length);
- for (String curve : curves) {
- curve = curve.trim();
- if (!curve.isEmpty()) {
- NamedEllipticCurve namedCurve =
- NamedEllipticCurve.getCurve(curve, requireFips);
- if (namedCurve != null) {
- if (isAvailableCurve(namedCurve.id)) {
- idList.add(namedCurve.id);
- }
- } // ignore unknown curves
- }
- }
- if (idList.isEmpty() && JsseJce.isEcAvailable()) {
- throw new IllegalArgumentException(
- "System property jdk.tls.namedGroups(" + property + ") " +
- "contains no supported elliptic curves");
- }
- } else { // default curves
- int[] ids;
- if (requireFips) {
- ids = new int[] {
- // only NIST curves in FIPS mode
- 23, 24, 25, 9, 10, 11, 12, 13, 14,
- };
- } else {
- ids = new int[] {
- // NIST curves first
- 23, 24, 25, 9, 10, 11, 12, 13, 14,
- // non-NIST curves
- 22,
- };
- }
-
- idList = new ArrayList<>(ids.length);
- for (int curveId : ids) {
- if (isAvailableCurve(curveId)) {
- idList.add(curveId);
- }
- }
- }
-
- if (debug != null && idList.isEmpty()) {
- Debug.log(
- "Initialized [jdk.tls.namedGroups|default] list contains " +
- "no available elliptic curves. " +
- (property != null ? "(" + property + ")" : "[Default]"));
- }
-
- supportedCurveIds = new int[idList.size()];
- int i = 0;
- for (Integer id : idList) {
- supportedCurveIds[i++] = id;
- }
- }
-
- // check whether the curve is supported by the underlying providers
- private static boolean isAvailableCurve(int curveId) {
- String oid = idToOidMap.get(curveId);
- if (oid != null) {
- AlgorithmParameters params = null;
- try {
- params = JsseJce.getAlgorithmParameters("EC");
- params.init(new ECGenParameterSpec(oid));
- } catch (Exception e) {
- return false;
- }
-
- // cache the parameters
- idToParams.put(curveId, params);
-
- return true;
- }
-
- return false;
- }
-
- private EllipticCurvesExtension(int[] curveIds) {
- super(ExtensionType.EXT_ELLIPTIC_CURVES);
-
- this.curveIds = curveIds;
- }
-
- EllipticCurvesExtension(HandshakeInStream s, int len)
- throws IOException {
- super(ExtensionType.EXT_ELLIPTIC_CURVES);
-
- int k = s.getInt16();
- if (((len & 1) != 0) || (k + 2 != len)) {
- throw new SSLProtocolException("Invalid " + type + " extension");
- }
-
- // Note: unknown curves will be ignored later.
- curveIds = new int[k >> 1];
- for (int i = 0; i < curveIds.length; i++) {
- curveIds[i] = s.getInt16();
- }
- }
-
- // get the preferred active curve
- static int getActiveCurves(AlgorithmConstraints constraints) {
- return getPreferredCurve(supportedCurveIds, constraints);
- }
-
- static boolean hasActiveCurves(AlgorithmConstraints constraints) {
- return getActiveCurves(constraints) >= 0;
- }
-
- static EllipticCurvesExtension createExtension(
- AlgorithmConstraints constraints) {
-
- ArrayList<Integer> idList = new ArrayList<>(supportedCurveIds.length);
- for (int curveId : supportedCurveIds) {
- if (constraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- "EC", idToParams.get(curveId))) {
- idList.add(curveId);
- }
- }
-
- if (!idList.isEmpty()) {
- int[] ids = new int[idList.size()];
- int i = 0;
- for (Integer id : idList) {
- ids[i++] = id;
- }
-
- return new EllipticCurvesExtension(ids);
- }
-
- return null;
- }
-
- // get the preferred activated curve
- int getPreferredCurve(AlgorithmConstraints constraints) {
- return getPreferredCurve(curveIds, constraints);
- }
-
- // get a preferred activated curve
- private static int getPreferredCurve(int[] curves,
- AlgorithmConstraints constraints) {
- for (int curveId : curves) {
- if (isSupported(curveId) && constraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- "EC", idToParams.get(curveId))) {
- return curveId;
- }
- }
-
- return -1;
- }
-
- boolean contains(int index) {
- for (int curveId : curveIds) {
- if (index == curveId) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- int length() {
- return 6 + (curveIds.length << 1);
- }
-
- @Override
- void send(HandshakeOutStream s) throws IOException {
- s.putInt16(type.id);
- int k = curveIds.length << 1;
- s.putInt16(k + 2);
- s.putInt16(k);
- for (int curveId : curveIds) {
- s.putInt16(curveId);
- }
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("Extension " + type + ", curve names: {");
- boolean first = true;
- for (int curveId : curveIds) {
- if (first) {
- first = false;
- } else {
- sb.append(", ");
- }
- // first check if it is a known named curve, then try other cases.
- String curveName = getCurveName(curveId);
- if (curveName != null) {
- sb.append(curveName);
- } else if (curveId == ARBITRARY_PRIME) {
- sb.append("arbitrary_explicit_prime_curves");
- } else if (curveId == ARBITRARY_CHAR2) {
- sb.append("arbitrary_explicit_char2_curves");
- } else {
- sb.append("unknown curve " + curveId);
- }
- }
- sb.append("}");
- return sb.toString();
- }
-
- // Test whether the given curve is supported.
- static boolean isSupported(int index) {
- for (int curveId : supportedCurveIds) {
- if (index == curveId) {
- return true;
- }
- }
-
- return false;
- }
-
- static int getCurveIndex(ECParameterSpec params) {
- String oid = JsseJce.getNamedCurveOid(params);
- if (oid == null) {
- return -1;
- }
- Integer n = oidToIdMap.get(oid);
- return (n == null) ? -1 : n;
- }
-
- static String getCurveOid(int index) {
- return idToOidMap.get(index);
- }
-
- static ECGenParameterSpec getECGenParamSpec(int index) {
- AlgorithmParameters params = idToParams.get(index);
- try {
- return params.getParameterSpec(ECGenParameterSpec.class);
- } catch (InvalidParameterSpecException ipse) {
- // should be unlikely
- String curveOid = getCurveOid(index);
- return new ECGenParameterSpec(curveOid);
- }
- }
-
- private static String getCurveName(int index) {
- for (NamedEllipticCurve namedCurve : NamedEllipticCurve.values()) {
- if (namedCurve.id == index) {
- return namedCurve.name;
- }
- }
-
- return null;
- }
-}
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ExtensionType.java Thu May 11 07:33:23 2017 +0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ExtensionType.java Wed May 10 23:40:46 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -82,9 +82,9 @@
static final ExtensionType EXT_CERT_TYPE =
e(0x0009, "cert_type"); // IANA registry value: 9
- // extensions defined in RFC 4492 (ECC)
- static final ExtensionType EXT_ELLIPTIC_CURVES =
- e(0x000A, "elliptic_curves"); // IANA registry value: 10
+ // extensions defined in RFC 4492 (ECC) and RFC 7919 (FFDHE)
+ static final ExtensionType EXT_SUPPORTED_GROUPS =
+ e(0x000A, "supported_groups"); // IANA registry value: 10
static final ExtensionType EXT_EC_POINT_FORMATS =
e(0x000B, "ec_point_formats"); // IANA registry value: 11
--- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java Thu May 11 07:33:23 2017 +0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java Wed May 10 23:40:46 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1369,8 +1369,9 @@
private static final int CURVE_EXPLICIT_CHAR2 = 2;
private static final int CURVE_NAMED_CURVE = 3;
- // id of the curve we are using
- private int curveId;
+ // id of the named group we are using
+ private int groupId;
+
// encoded public point
private byte[] pointBytes;
@@ -1389,7 +1390,8 @@
ECDH_ServerKeyExchange(ECDHCrypt obj, PrivateKey privateKey,
byte[] clntNonce, byte[] svrNonce, SecureRandom sr,
SignatureAndHashAlgorithm signAlgorithm,
- ProtocolVersion protocolVersion) throws GeneralSecurityException {
+ ProtocolVersion protocolVersion)
+ throws SSLHandshakeException, GeneralSecurityException {
this.protocolVersion = protocolVersion;
@@ -1397,7 +1399,14 @@
ECParameterSpec params = publicKey.getParams();
ECPoint point = publicKey.getW();
pointBytes = JsseJce.encodePoint(point, params.getCurve());
- curveId = EllipticCurvesExtension.getCurveIndex(params);
+
+ NamedGroup namedGroup = NamedGroup.valueOf(params);
+ if ((namedGroup == null) || (namedGroup.oid == null) ){
+ // unlikely
+ throw new SSLHandshakeException(
+ "Unnamed EC parameter spec: " + params);
+ }
+ groupId = namedGroup.id;
if (privateKey == null) {
// ECDH_anon
@@ -1434,20 +1443,27 @@
// These parsing errors should never occur as we negotiated
// the supported curves during the exchange of the Hello messages.
if (curveType == CURVE_NAMED_CURVE) {
- curveId = input.getInt16();
- if (!EllipticCurvesExtension.isSupported(curveId)) {
+ groupId = input.getInt16();
+ NamedGroup namedGroup = NamedGroup.valueOf(groupId);
+ if (namedGroup == null) {
throw new SSLHandshakeException(
- "Unsupported curveId: " + curveId);
+ "Unknown named group ID: " + groupId);
}
- String curveOid = EllipticCurvesExtension.getCurveOid(curveId);
- if (curveOid == null) {
+
+ if (!SupportedGroupsExtension.supports(namedGroup)) {
throw new SSLHandshakeException(
- "Unknown named curve: " + curveId);
+ "Unsupported named group: " + namedGroup);
}
- parameters = JsseJce.getECParameterSpec(curveOid);
+
+ if (namedGroup.oid == null) {
+ throw new SSLHandshakeException(
+ "Unknown named EC curve: " + namedGroup);
+ }
+
+ parameters = JsseJce.getECParameterSpec(namedGroup.oid);
if (parameters == null) {
throw new SSLHandshakeException(
- "Unsupported curve: " + curveOid);
+ "No supported EC parameter for named group: " + namedGroup);
}
} else {
throw new SSLHandshakeException(
@@ -1530,8 +1546,8 @@
sig.update(svrNonce);
sig.update((byte)CURVE_NAMED_CURVE);
- sig.update((byte)(curveId >> 8));
- sig.update((byte)curveId);
+ sig.update((byte)(groupId >> 8));
+ sig.update((byte)groupId);
sig.update((byte)pointBytes.length);
sig.update(pointBytes);
}
@@ -1552,7 +1568,7 @@
@Override
void send(HandshakeOutStream s) throws IOException {
s.putInt8(CURVE_NAMED_CURVE);
- s.putInt16(curveId);
+ s.putInt16(groupId);
s.putBytes8(pointBytes);
if (signatureBytes != null) {
--- a/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java Thu May 11 07:33:23 2017 +0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java Wed May 10 23:40:46 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -52,6 +52,7 @@
import static sun.security.ssl.CipherSuite.PRF.*;
import static sun.security.ssl.CipherSuite.CipherType.*;
+import static sun.security.ssl.NamedGroupType.*;
/**
* Handshaker ... processes handshake records from an SSL V3.0
@@ -685,42 +686,14 @@
ArrayList<CipherSuite> suites = new ArrayList<>();
if (!(activeProtocols.collection().isEmpty()) &&
activeProtocols.min.v != ProtocolVersion.NONE.v) {
- boolean checkedCurves = false;
- boolean hasCurves = false;
+ Map<NamedGroupType, Boolean> cachedStatus =
+ new EnumMap<>(NamedGroupType.class);
for (CipherSuite suite : enabledCipherSuites.collection()) {
- if (!activeProtocols.min.obsoletes(suite) &&
+ if (suite.isAvailable() &&
+ (!activeProtocols.min.obsoletes(suite)) &&
activeProtocols.max.supports(suite)) {
- if (algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- suite.name, null)) {
-
- boolean available = true;
- if (suite.keyExchange.isEC) {
- if (!checkedCurves) {
- hasCurves = EllipticCurvesExtension
- .hasActiveCurves(algorithmConstraints);
- checkedCurves = true;
-
- if (!hasCurves && debug != null &&
- Debug.isOn("verbose")) {
- System.out.println(
- "No available elliptic curves");
- }
- }
-
- available = hasCurves;
-
- if (!available && debug != null &&
- Debug.isOn("verbose")) {
- System.out.println(
- "No active elliptic curves, ignore " +
- suite);
- }
- }
-
- if (available) {
- suites.add(suite);
- }
+ if (isActivatable(suite, cachedStatus)) {
+ suites.add(suite);
}
} else if (debug != null && Debug.isOn("verbose")) {
if (activeProtocols.min.obsoletes(suite)) {
@@ -779,46 +752,15 @@
}
boolean found = false;
+ Map<NamedGroupType, Boolean> cachedStatus =
+ new EnumMap<>(NamedGroupType.class);
for (CipherSuite suite : enabledCipherSuites.collection()) {
if (suite.isAvailable() && (!protocol.obsoletes(suite)) &&
protocol.supports(suite)) {
- if (algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- suite.name, null)) {
-
- boolean available = true;
- if (suite.keyExchange.isEC) {
- if (!checkedCurves) {
- hasCurves = EllipticCurvesExtension
- .hasActiveCurves(algorithmConstraints);
- checkedCurves = true;
-
- if (!hasCurves && debug != null &&
- Debug.isOn("verbose")) {
- System.out.println(
- "No activated elliptic curves");
- }
- }
-
- available = hasCurves;
-
- if (!available && debug != null &&
- Debug.isOn("verbose")) {
- System.out.println(
- "No active elliptic curves, ignore " +
- suite + " for " + protocol);
- }
- }
-
- if (available) {
- protocols.add(protocol);
- found = true;
- break;
- }
- } else if (debug != null && Debug.isOn("verbose")) {
- System.out.println(
- "Ignoring disabled cipher suite: " + suite +
- " for " + protocol);
+ if (isActivatable(suite, cachedStatus)) {
+ protocols.add(protocol);
+ found = true;
+ break;
}
} else if (debug != null && Debug.isOn("verbose")) {
System.out.println(
@@ -826,6 +768,7 @@
" for " + protocol);
}
}
+
if (!found && (debug != null) && Debug.isOn("handshake")) {
System.out.println(
"No available cipher suite for " + protocol);
@@ -842,6 +785,43 @@
return activeProtocols;
}
+ private boolean isActivatable(CipherSuite suite,
+ Map<NamedGroupType, Boolean> cachedStatus) {
+
+ if (algorithmConstraints.permits(
+ EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), suite.name, null)) {
+ boolean available = true;
+ NamedGroupType groupType = suite.keyExchange.groupType;
+ if (groupType != NAMED_GROUP_NONE) {
+ Boolean checkedStatus = cachedStatus.get(groupType);
+ if (checkedStatus == null) {
+ available = SupportedGroupsExtension.isActivatable(
+ algorithmConstraints, groupType);
+ cachedStatus.put(groupType, available);
+
+ if (!available && debug != null && Debug.isOn("verbose")) {
+ System.out.println("No activated named group");
+ }
+ } else {
+ available = checkedStatus.booleanValue();
+ }
+
+ if (!available && debug != null && Debug.isOn("verbose")) {
+ System.out.println(
+ "No active named group, ignore " + suite);
+ }
+
+ return available;
+ } else {
+ return true;
+ }
+ } else if (debug != null && Debug.isOn("verbose")) {
+ System.out.println("Ignoring disabled cipher suite: " + suite);
+ }
+
+ return false;
+ }
+
/**
* As long as handshaking has not activated, we can
* change whether session creations are allowed.
--- a/jdk/src/java.base/share/classes/sun/security/ssl/HelloExtensions.java Thu May 11 07:33:23 2017 +0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/HelloExtensions.java Wed May 10 23:40:46 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -49,7 +49,7 @@
* explicitly support.
* . ServerNameExtension: the server_name extension.
* . SignatureAlgorithmsExtension: the signature_algorithms extension.
- * . EllipticCurvesExtension: the ECC supported curves extension.
+ * . SupportedGroupsExtension: the supported groups extension.
* . EllipticPointFormatsExtension: the ECC supported point formats
* (compressed/uncompressed) extension.
* . ALPNExtension: the application_layer_protocol_negotiation extension.
@@ -79,8 +79,8 @@
extension = new ServerNameExtension(s, extlen);
} else if (extType == ExtensionType.EXT_SIGNATURE_ALGORITHMS) {
extension = new SignatureAlgorithmsExtension(s, extlen);
- } else if (extType == ExtensionType.EXT_ELLIPTIC_CURVES) {
- extension = new EllipticCurvesExtension(s, extlen);
+ } else if (extType == ExtensionType.EXT_SUPPORTED_GROUPS) {
+ extension = new SupportedGroupsExtension(s, extlen);
} else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) {
extension = new EllipticPointFormatsExtension(s, extlen);
} else if (extType == ExtensionType.EXT_RENEGOTIATION_INFO) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/NamedGroup.java Wed May 10 23:40:46 2017 +0000
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ssl;
+
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECGenParameterSpec;
+import static sun.security.ssl.NamedGroupType.*;
+
+enum NamedGroup {
+ // Elliptic Curves (RFC 4492)
+ //
+ // See sun.security.util.CurveDB for the OIDs
+
+ // NIST K-163
+ SECT163_K1(1, NAMED_GROUP_ECDHE, "sect163k1", "1.3.132.0.1", true),
+
+ SECT163_R1(2, NAMED_GROUP_ECDHE, "sect163r1", "1.3.132.0.2", false),
+
+ // NIST B-163
+ SECT163_R2(3, NAMED_GROUP_ECDHE, "sect163r2", "1.3.132.0.15", true),
+
+ SECT193_R1(4, NAMED_GROUP_ECDHE, "sect193r1", "1.3.132.0.24", false),
+ SECT193_R2(5, NAMED_GROUP_ECDHE, "sect193r2", "1.3.132.0.25", false),
+
+ // NIST K-233
+ SECT233_K1(6, NAMED_GROUP_ECDHE, "sect233k1", "1.3.132.0.26", true),
+
+ // NIST B-233
+ SECT233_R1(7, NAMED_GROUP_ECDHE, "sect233r1", "1.3.132.0.27", true),
+
+ SECT239_K1(8, NAMED_GROUP_ECDHE, "sect239k1", "1.3.132.0.3", false),
+
+ // NIST K-283
+ SECT283_K1(9, NAMED_GROUP_ECDHE, "sect283k1", "1.3.132.0.16", true),
+
+ // NIST B-283
+ SECT283_R1(10, NAMED_GROUP_ECDHE, "sect283r1", "1.3.132.0.17", true),
+
+ // NIST K-409
+ SECT409_K1(11, NAMED_GROUP_ECDHE, "sect409k1", "1.3.132.0.36", true),
+
+ // NIST B-409
+ SECT409_R1(12, NAMED_GROUP_ECDHE, "sect409r1", "1.3.132.0.37", true),
+
+ // NIST K-571
+ SECT571_K1(13, NAMED_GROUP_ECDHE, "sect571k1", "1.3.132.0.38", true),
+
+ // NIST B-571
+ SECT571_R1(14, NAMED_GROUP_ECDHE, "sect571r1", "1.3.132.0.39", true),
+
+ SECP160_K1(15, NAMED_GROUP_ECDHE, "secp160k1", "1.3.132.0.9", false),
+ SECP160_R1(16, NAMED_GROUP_ECDHE, "secp160r1", "1.3.132.0.8", false),
+ SECP160_R2(17, NAMED_GROUP_ECDHE, "secp160r2", "1.3.132.0.30", false),
+ SECP192_K1(18, NAMED_GROUP_ECDHE, "secp192k1", "1.3.132.0.31", false),
+
+ // NIST P-192
+ SECP192_R1(19, NAMED_GROUP_ECDHE, "secp192r1", "1.2.840.10045.3.1.1", true),
+
+ SECP224_K1(20, NAMED_GROUP_ECDHE, "secp224k1", "1.3.132.0.32", false),
+ // NIST P-224
+ SECP224_R1(21, NAMED_GROUP_ECDHE, "secp224r1", "1.3.132.0.33", true),
+
+ SECP256_K1(22, NAMED_GROUP_ECDHE, "secp256k1", "1.3.132.0.10", false),
+
+ // NIST P-256
+ SECP256_R1(23, NAMED_GROUP_ECDHE, "secp256r1", "1.2.840.10045.3.1.7", true),
+
+ // NIST P-384
+ SECP384_R1(24, NAMED_GROUP_ECDHE, "secp384r1", "1.3.132.0.34", true),
+
+ // NIST P-521
+ SECP521_R1(25, NAMED_GROUP_ECDHE, "secp521r1", "1.3.132.0.35", true),
+
+ // Finite Field Diffie-Hellman Ephemeral Parameters (RFC 7919)
+ FFDHE_2048(256, NAMED_GROUP_FFDHE, "ffdhe2048", true),
+ FFDHE_3072(257, NAMED_GROUP_FFDHE, "ffdhe3072", true),
+ FFDHE_4096(258, NAMED_GROUP_FFDHE, "ffdhe4096", true),
+ FFDHE_6144(259, NAMED_GROUP_FFDHE, "ffdhe6144", true),
+ FFDHE_8192(260, NAMED_GROUP_FFDHE, "ffdhe8192", true);
+
+ int id;
+ NamedGroupType type;
+ String name;
+ String oid;
+ String algorithm;
+ boolean isFips;
+
+ // Constructor used for Elliptic Curve Groups (ECDHE)
+ NamedGroup(int id, NamedGroupType type,
+ String name, String oid, boolean isFips) {
+ this.id = id;
+ this.type = type;
+ this.name = name;
+ this.oid = oid;
+ this.algorithm = "EC";
+ this.isFips = isFips;
+ }
+
+ // Constructor used for Finite Field Diffie-Hellman Groups (FFDHE)
+ NamedGroup(int id, NamedGroupType type, String name, boolean isFips) {
+ this.id = id;
+ this.type = type;
+ this.name = name;
+ this.oid = null;
+ this.algorithm = "DiffieHellman";
+ this.isFips = isFips;
+ }
+
+ static NamedGroup valueOf(int id) {
+ for (NamedGroup group : NamedGroup.values()) {
+ if (group.id == id) {
+ return group;
+ }
+ }
+
+ return null;
+ }
+
+ static NamedGroup nameOf(String name) {
+ for (NamedGroup group : NamedGroup.values()) {
+ if (group.name.equals(name)) {
+ return group;
+ }
+ }
+
+ return null;
+ }
+
+ static NamedGroup valueOf(ECParameterSpec params) {
+ String oid = JsseJce.getNamedCurveOid(params);
+ if ((oid != null) && (!oid.isEmpty())) {
+ for (NamedGroup group : NamedGroup.values()) {
+ if (oid.equals(group.oid)) {
+ return group;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return this.name;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/NamedGroupType.java Wed May 10 23:40:46 2017 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ssl;
+
+enum NamedGroupType {
+ NAMED_GROUP_ECDHE, // Elliptic Curve Groups (ECDHE)
+ NAMED_GROUP_FFDHE, // Finite Field Groups (DHE)
+ NAMED_GROUP_NONE // No predefined named group
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/PredefinedDHParameterSpecs.java Wed May 10 23:40:46 2017 +0000
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ssl;
+
+import java.security.*;
+import java.math.BigInteger;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Collections;
+import javax.crypto.spec.DHParameterSpec;
+
+/**
+ * Predefined default DH ephemeral parameters.
+ */
+final class PredefinedDHParameterSpecs {
+ private final static boolean debugIsOn =
+ (Debug.getInstance("ssl") != null) && Debug.isOn("sslctx");
+
+ //
+ // Default DH ephemeral parameters
+ //
+ private static final BigInteger p512 = new BigInteger( // generated
+ "D87780E15FF50B4ABBE89870188B049406B5BEA98AB23A02" +
+ "41D88EA75B7755E669C08093D3F0CA7FC3A5A25CF067DCB9" +
+ "A43DD89D1D90921C6328884461E0B6D3", 16);
+ private static final BigInteger p768 = new BigInteger( // RFC 2409
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
+ "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF", 16);
+
+ private static final BigInteger p1024 = new BigInteger( // RFC 2409
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" +
+ "FFFFFFFFFFFFFFFF", 16);
+ private static final BigInteger p1536 = new BigInteger( // RFC 3526
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" +
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
+ "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 16);
+ private static final BigInteger p2048 = new BigInteger( // TLS FFDHE
+ "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
+ "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
+ "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
+ "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
+ "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
+ "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
+ "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
+ "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
+ "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
+ "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
+ "886B423861285C97FFFFFFFFFFFFFFFF", 16);
+ private static final BigInteger p3072 = new BigInteger( // TLS FFDHE
+ "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
+ "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
+ "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
+ "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
+ "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
+ "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
+ "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
+ "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
+ "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
+ "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
+ "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
+ "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
+ "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
+ "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
+ "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
+ "3C1B20EE3FD59D7C25E41D2B66C62E37FFFFFFFFFFFFFFFF", 16);
+ private static final BigInteger p4096 = new BigInteger( // TLS FFDHE
+ "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
+ "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
+ "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
+ "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
+ "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
+ "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
+ "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
+ "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
+ "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
+ "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
+ "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
+ "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
+ "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
+ "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
+ "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
+ "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" +
+ "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004" +
+ "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" +
+ "A907600A918130C46DC778F971AD0038092999A333CB8B7A" +
+ "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" +
+ "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E655F6A" +
+ "FFFFFFFFFFFFFFFF", 16);
+ private static final BigInteger p6144 = new BigInteger( // TLS FFDHE
+ "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
+ "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
+ "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
+ "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
+ "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
+ "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
+ "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
+ "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
+ "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
+ "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
+ "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
+ "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
+ "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
+ "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
+ "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
+ "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" +
+ "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004" +
+ "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" +
+ "A907600A918130C46DC778F971AD0038092999A333CB8B7A" +
+ "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" +
+ "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD902" +
+ "0BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA6" +
+ "3BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3A" +
+ "CDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477" +
+ "A52471F7A9A96910B855322EDB6340D8A00EF092350511E3" +
+ "0ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4" +
+ "763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6" +
+ "B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538C" +
+ "D72B03746AE77F5E62292C311562A846505DC82DB854338A" +
+ "E49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B04" +
+ "5B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1" +
+ "A41D570D7938DAD4A40E329CD0E40E65FFFFFFFFFFFFFFFF", 16);
+ private static final BigInteger p8192 = new BigInteger( // TLS FFDHE
+ "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" +
+ "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" +
+ "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" +
+ "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" +
+ "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" +
+ "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" +
+ "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" +
+ "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" +
+ "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" +
+ "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" +
+ "886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C0238" +
+ "61B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91C" +
+ "AEFE130985139270B4130C93BC437944F4FD4452E2D74DD3" +
+ "64F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0D" +
+ "ABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF" +
+ "3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB" +
+ "7930E9E4E58857B6AC7D5F42D69F6D187763CF1D55034004" +
+ "87F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832" +
+ "A907600A918130C46DC778F971AD0038092999A333CB8B7A" +
+ "1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF" +
+ "8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD902" +
+ "0BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA6" +
+ "3BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3A" +
+ "CDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477" +
+ "A52471F7A9A96910B855322EDB6340D8A00EF092350511E3" +
+ "0ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4" +
+ "763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6" +
+ "B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538C" +
+ "D72B03746AE77F5E62292C311562A846505DC82DB854338A" +
+ "E49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B04" +
+ "5B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1" +
+ "A41D570D7938DAD4A40E329CCFF46AAA36AD004CF600C838" +
+ "1E425A31D951AE64FDB23FCEC9509D43687FEB69EDD1CC5E" +
+ "0B8CC3BDF64B10EF86B63142A3AB8829555B2F747C932665" +
+ "CB2C0F1CC01BD70229388839D2AF05E454504AC78B758282" +
+ "2846C0BA35C35F5C59160CC046FD8251541FC68C9C86B022" +
+ "BB7099876A460E7451A8A93109703FEE1C217E6C3826E52C" +
+ "51AA691E0E423CFC99E9E31650C1217B624816CDAD9A95F9" +
+ "D5B8019488D9C0A0A1FE3075A577E23183F81D4A3F2FA457" +
+ "1EFC8CE0BA8A4FE8B6855DFE72B0A66EDED2FBABFBE58A30" +
+ "FAFABE1C5D71A87E2F741EF8C1FE86FEA6BBFDE530677F0D" +
+ "97D11D49F7A8443D0822E506A9F4614E011E2A94838FF88C" +
+ "D68C8BB7C5C6424CFFFFFFFFFFFFFFFF", 16);
+
+ private static final BigInteger[] supportedPrimes = {
+ p512, p768, p1024, p1536, p2048, p3072, p4096, p6144, p8192};
+
+ private static final BigInteger[] ffdhePrimes = {
+ p2048, p3072, p4096, p6144, p8192};
+
+ // a measure of the uncertainty that prime modulus p is not a prime
+ //
+ // see BigInteger.isProbablePrime(int certainty)
+ private final static int PRIME_CERTAINTY = 120;
+
+ // the known security property, jdk.tls.server.defaultDHEParameters
+ private final static String PROPERTY_NAME =
+ "jdk.tls.server.defaultDHEParameters";
+
+ private static final Pattern spacesPattern = Pattern.compile("\\s+");
+
+ private final static Pattern syntaxPattern = Pattern.compile(
+ "(\\{[0-9A-Fa-f]+,[0-9A-Fa-f]+\\})" +
+ "(,\\{[0-9A-Fa-f]+,[0-9A-Fa-f]+\\})*");
+
+ private static final Pattern paramsPattern = Pattern.compile(
+ "\\{([0-9A-Fa-f]+),([0-9A-Fa-f]+)\\}");
+
+ // cache of predefined default DH ephemeral parameters
+ final static Map<Integer, DHParameterSpec> definedParams;
+
+ // cache of Finite Field DH Ephemeral parameters (RFC 7919/FFDHE)
+ final static Map<Integer, DHParameterSpec> ffdheParams;
+
+ static {
+ String property = AccessController.doPrivileged(
+ new PrivilegedAction<String>() {
+ public String run() {
+ return Security.getProperty(PROPERTY_NAME);
+ }
+ });
+
+ if (property != null && !property.isEmpty()) {
+ // remove double quote marks from beginning/end of the property
+ if (property.length() >= 2 && property.charAt(0) == '"' &&
+ property.charAt(property.length() - 1) == '"') {
+ property = property.substring(1, property.length() - 1);
+ }
+
+ property = property.trim();
+ }
+
+ if (property != null && !property.isEmpty()) {
+ Matcher spacesMatcher = spacesPattern.matcher(property);
+ property = spacesMatcher.replaceAll("");
+
+ if (debugIsOn) {
+ System.out.println("The Security Property " +
+ PROPERTY_NAME + ": " + property);
+ }
+ }
+
+ Map<Integer,DHParameterSpec> defaultParams = new HashMap<>();
+ if (property != null && !property.isEmpty()) {
+ Matcher syntaxMatcher = syntaxPattern.matcher(property);
+ if (syntaxMatcher.matches()) {
+ Matcher paramsFinder = paramsPattern.matcher(property);
+ while(paramsFinder.find()) {
+ String primeModulus = paramsFinder.group(1);
+ BigInteger p = new BigInteger(primeModulus, 16);
+ if (!p.isProbablePrime(PRIME_CERTAINTY)) {
+ if (debugIsOn) {
+ System.out.println(
+ "Prime modulus p in Security Property, " +
+ PROPERTY_NAME + ", is not a prime: " +
+ primeModulus);
+ }
+
+ continue;
+ }
+
+ String baseGenerator = paramsFinder.group(2);
+ BigInteger g = new BigInteger(baseGenerator, 16);
+
+ DHParameterSpec spec = new DHParameterSpec(p, g);
+ int primeLen = p.bitLength();
+ defaultParams.put(primeLen, spec);
+ }
+ } else if (debugIsOn) {
+ System.out.println("Invalid Security Property, " +
+ PROPERTY_NAME + ", definition");
+ }
+ }
+
+ Map<Integer,DHParameterSpec> tempFFDHEs = new HashMap<>();
+ for (BigInteger p : ffdhePrimes) {
+ int primeLen = p.bitLength();
+ DHParameterSpec dhps = new DHParameterSpec(p, BigInteger.TWO);
+ tempFFDHEs.put(primeLen, dhps);
+ defaultParams.putIfAbsent(primeLen, dhps);
+ }
+
+ for (BigInteger p : supportedPrimes) {
+ int primeLen = p.bitLength();
+ if (defaultParams.get(primeLen) == null) {
+ defaultParams.put(primeLen,
+ new DHParameterSpec(p, BigInteger.TWO));
+ }
+ }
+
+ ffdheParams =
+ Collections.<Integer,DHParameterSpec>unmodifiableMap(tempFFDHEs);
+ definedParams =
+ Collections.<Integer,DHParameterSpec>unmodifiableMap(defaultParams);
+ }
+}
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java Thu May 11 07:33:23 2017 +0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java Wed May 10 23:40:46 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -96,7 +96,7 @@
private ProtocolVersion clientRequestedVersion;
// client supported elliptic curves
- private EllipticCurvesExtension requestedCurves;
+ private SupportedGroupsExtension requestedGroups;
// the preferable signature algorithm used by ServerKeyExchange message
SignatureAndHashAlgorithm preferableSignatureAlgorithm;
@@ -751,8 +751,8 @@
throw new SSLException("Client did not resume a session");
}
- requestedCurves = (EllipticCurvesExtension)
- mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES);
+ requestedGroups = (SupportedGroupsExtension)
+ mesg.extensions.get(ExtensionType.EXT_SUPPORTED_GROUPS);
// We only need to handle the "signature_algorithm" extension
// for full handshakes and TLS 1.2 or later.
@@ -1341,6 +1341,8 @@
}
}
+ // The named group used for ECDHE and FFDHE.
+ NamedGroup namedGroup = null;
switch (keyExchange) {
case K_RSA:
// need RSA certs for authentication
@@ -1366,6 +1368,37 @@
}
break;
case K_DHE_RSA:
+ // Is ephemeral DH cipher suite usable for the connection?
+ //
+ // [RFC 7919] If a compatible TLS server receives a Supported
+ // Groups extension from a client that includes any FFDHE group
+ // (i.e., any codepoint between 256 and 511, inclusive, even if
+ // unknown to the server), and if none of the client-proposed
+ // FFDHE groups are known and acceptable to the server, then
+ // the server MUST NOT select an FFDHE cipher suite. In this
+ // case, the server SHOULD select an acceptable non-FFDHE cipher
+ // suite from the client's offered list. If the extension is
+ // present with FFDHE groups, none of the client's offered
+ // groups are acceptable by the server, and none of the client's
+ // proposed non-FFDHE cipher suites are acceptable to the server,
+ // the server MUST end the connection with a fatal TLS alert
+ // of type insufficient_security(71).
+ //
+ // Note: For compatibility, if an application is customized to
+ // use legacy sizes (512 bits for exportable cipher suites and
+ // 768 bits for others), or the cipher suite is exportable, the
+ // FFDHE extension will not be used.
+ if ((!useLegacyEphemeralDHKeys) && (!suite.exportable) &&
+ (requestedGroups != null) && requestedGroups.hasFFDHEGroup()) {
+
+ namedGroup = requestedGroups.getPreferredGroup(
+ algorithmConstraints, NamedGroupType.NAMED_GROUP_FFDHE);
+ if (namedGroup == null) {
+ // no match found, cannot use this cipher suite.
+ return false;
+ }
+ }
+
// need RSA certs for authentication
if (setupPrivateKeyAndChain("RSA") == false) {
return false;
@@ -1386,9 +1419,20 @@
}
}
- setupEphemeralDHKeys(suite.exportable, privateKey);
+ setupEphemeralDHKeys(namedGroup, suite.exportable, privateKey);
break;
case K_ECDHE_RSA:
+ // Is ECDHE cipher suite usable for the connection?
+ namedGroup = (requestedGroups != null) ?
+ requestedGroups.getPreferredGroup(
+ algorithmConstraints, NamedGroupType.NAMED_GROUP_ECDHE) :
+ SupportedGroupsExtension.getPreferredECGroup(
+ algorithmConstraints);
+ if (namedGroup == null) {
+ // no match found, cannot use this ciphersuite
+ return false;
+ }
+
// need RSA certs for authentication
if (setupPrivateKeyAndChain("RSA") == false) {
return false;
@@ -1409,11 +1453,23 @@
}
}
- if (setupEphemeralECDHKeys() == false) {
- return false;
- }
+ setupEphemeralECDHKeys(namedGroup);
break;
case K_DHE_DSS:
+ // Is ephemeral DH cipher suite usable for the connection?
+ //
+ // See comment in K_DHE_RSA case.
+ if ((!useLegacyEphemeralDHKeys) && (!suite.exportable) &&
+ (requestedGroups != null) && requestedGroups.hasFFDHEGroup()) {
+
+ namedGroup = requestedGroups.getPreferredGroup(
+ algorithmConstraints, NamedGroupType.NAMED_GROUP_FFDHE);
+ if (namedGroup == null) {
+ // no match found, cannot use this cipher suite.
+ return false;
+ }
+ }
+
// get preferable peer signature algorithm for server key exchange
if (protocolVersion.useTLS12PlusSpec()) {
preferableSignatureAlgorithm =
@@ -1434,9 +1490,20 @@
return false;
}
- setupEphemeralDHKeys(suite.exportable, privateKey);
+ setupEphemeralDHKeys(namedGroup, suite.exportable, privateKey);
break;
case K_ECDHE_ECDSA:
+ // Is ECDHE cipher suite usable for the connection?
+ namedGroup = (requestedGroups != null) ?
+ requestedGroups.getPreferredGroup(
+ algorithmConstraints, NamedGroupType.NAMED_GROUP_ECDHE) :
+ SupportedGroupsExtension.getPreferredECGroup(
+ algorithmConstraints);
+ if (namedGroup == null) {
+ // no match found, cannot use this ciphersuite
+ return false;
+ }
+
// get preferable peer signature algorithm for server key exchange
if (protocolVersion.useTLS12PlusSpec()) {
preferableSignatureAlgorithm =
@@ -1456,9 +1523,8 @@
if (setupPrivateKeyAndChain("EC") == false) {
return false;
}
- if (setupEphemeralECDHKeys() == false) {
- return false;
- }
+
+ setupEphemeralECDHKeys(namedGroup);
break;
case K_ECDH_RSA:
// need EC cert
@@ -1475,14 +1541,36 @@
setupStaticECDHKeys();
break;
case K_DH_ANON:
+ // Is ephemeral DH cipher suite usable for the connection?
+ //
+ // See comment in K_DHE_RSA case.
+ if ((!useLegacyEphemeralDHKeys) && (!suite.exportable) &&
+ (requestedGroups != null) && requestedGroups.hasFFDHEGroup()) {
+ namedGroup = requestedGroups.getPreferredGroup(
+ algorithmConstraints, NamedGroupType.NAMED_GROUP_FFDHE);
+ if (namedGroup == null) {
+ // no match found, cannot use this cipher suite.
+ return false;
+ }
+ }
+
// no certs needed for anonymous
- setupEphemeralDHKeys(suite.exportable, null);
+ setupEphemeralDHKeys(namedGroup, suite.exportable, null);
break;
case K_ECDH_ANON:
- // no certs needed for anonymous
- if (setupEphemeralECDHKeys() == false) {
+ // Is ECDHE cipher suite usable for the connection?
+ namedGroup = (requestedGroups != null) ?
+ requestedGroups.getPreferredGroup(
+ algorithmConstraints, NamedGroupType.NAMED_GROUP_ECDHE) :
+ SupportedGroupsExtension.getPreferredECGroup(
+ algorithmConstraints);
+ if (namedGroup == null) {
+ // no match found, cannot use this ciphersuite
return false;
}
+
+ // no certs needed for anonymous
+ setupEphemeralECDHKeys(namedGroup);
break;
default:
ClientKeyExchangeService p =
@@ -1544,7 +1632,15 @@
* Acquire some "ephemeral" Diffie-Hellman keys for this handshake.
* We don't reuse these, for improved forward secrecy.
*/
- private void setupEphemeralDHKeys(boolean export, Key key) {
+ private void setupEphemeralDHKeys(
+ NamedGroup namedGroup, boolean export, Key key) {
+ // Are the client and server willing to negotiate FFDHE groups?
+ if ((!useLegacyEphemeralDHKeys) && (!export) && (namedGroup != null)) {
+ dh = new DHCrypt(namedGroup, sslContext.getSecureRandom());
+
+ return;
+ } // Otherwise, the client is not compatible with FFDHE extension.
+
/*
* 768 bits ephemeral DH private keys were used to be used in
* ServerKeyExchange except that exportable ciphers max out at 512
@@ -1613,20 +1709,11 @@
dh = new DHCrypt(keySize, sslContext.getSecureRandom());
}
- // Setup the ephemeral ECDH parameters.
- // If we cannot continue because we do not support any of the curves that
- // the client requested, return false. Otherwise (all is well), return true.
- private boolean setupEphemeralECDHKeys() {
- int index = (requestedCurves != null) ?
- requestedCurves.getPreferredCurve(algorithmConstraints) :
- EllipticCurvesExtension.getActiveCurves(algorithmConstraints);
- if (index < 0) {
- // no match found, cannot use this ciphersuite
- return false;
- }
-
- ecdh = new ECDHCrypt(index, sslContext.getSecureRandom());
- return true;
+ /**
+ * Setup the ephemeral ECDH parameters.
+ */
+ private void setupEphemeralECDHKeys(NamedGroup namedGroup) {
+ ecdh = new ECDHCrypt(namedGroup, sslContext.getSecureRandom());
}
private void setupStaticECDHKeys() {
@@ -1674,9 +1761,11 @@
return false;
}
ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
- int id = EllipticCurvesExtension.getCurveIndex(params);
- if ((id <= 0) || !EllipticCurvesExtension.isSupported(id) ||
- ((requestedCurves != null) && !requestedCurves.contains(id))) {
+ NamedGroup namedGroup = NamedGroup.valueOf(params);
+ if ((namedGroup == null) ||
+ (!SupportedGroupsExtension.supports(namedGroup)) ||
+ ((requestedGroups != null) &&
+ !requestedGroups.contains(namedGroup.id))) {
return false;
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java Wed May 10 23:40:46 2017 +0000
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ssl;
+
+import java.io.IOException;
+import java.security.spec.ECGenParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.AlgorithmParameters;
+import java.security.AlgorithmConstraints;
+import java.security.CryptoPrimitive;
+import java.security.AccessController;
+import java.security.spec.AlgorithmParameterSpec;
+import javax.crypto.spec.DHParameterSpec;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ArrayList;
+import javax.net.ssl.SSLProtocolException;
+
+import sun.security.action.GetPropertyAction;
+
+//
+// Note: Since RFC 7919, the extension's semantics are expanded from
+// "Supported Elliptic Curves" to "Supported Groups". The enum datatype
+// used in the extension has been renamed from NamedCurve to NamedGroup.
+// Its semantics are likewise expanded from "named curve" to "named group".
+//
+final class SupportedGroupsExtension extends HelloExtension {
+
+ /* Class and subclass dynamic debugging support */
+ private static final Debug debug = Debug.getInstance("ssl");
+
+ private static final int ARBITRARY_PRIME = 0xff01;
+ private static final int ARBITRARY_CHAR2 = 0xff02;
+
+ // cache to speed up the parameters construction
+ private static final Map<NamedGroup,
+ AlgorithmParameters> namedGroupParams = new HashMap<>();
+
+ // the supported named groups
+ private static final NamedGroup[] supportedNamedGroups;
+
+ // the named group presented in the extension
+ private final int[] requestedNamedGroupIds;
+
+ static {
+ boolean requireFips = SunJSSE.isFIPS();
+
+ // The value of the System Property defines a list of enabled named
+ // groups in preference order, separated with comma. For example:
+ //
+ // jdk.tls.namedGroups="secp521r1, secp256r1, ffdhe2048"
+ //
+ // If the System Property is not defined or the value is empty, the
+ // default groups and preferences will be used.
+ String property = AccessController.doPrivileged(
+ new GetPropertyAction("jdk.tls.namedGroups"));
+ if (property != null && property.length() != 0) {
+ // remove double quote marks from beginning/end of the property
+ if (property.length() > 1 && property.charAt(0) == '"' &&
+ property.charAt(property.length() - 1) == '"') {
+ property = property.substring(1, property.length() - 1);
+ }
+ }
+
+ ArrayList<NamedGroup> groupList;
+ if (property != null && property.length() != 0) { // customized groups
+ String[] groups = property.split(",");
+ groupList = new ArrayList<>(groups.length);
+ for (String group : groups) {
+ group = group.trim();
+ if (!group.isEmpty()) {
+ NamedGroup namedGroup = NamedGroup.nameOf(group);
+ if (namedGroup != null &&
+ (!requireFips || namedGroup.isFips)) {
+ if (isAvailableGroup(namedGroup)) {
+ groupList.add(namedGroup);
+ }
+ } // ignore unknown groups
+ }
+ }
+
+ if (groupList.isEmpty() && JsseJce.isEcAvailable()) {
+ throw new IllegalArgumentException(
+ "System property jdk.tls.namedGroups(" + property + ") " +
+ "contains no supported elliptic curves");
+ }
+ } else { // default groups
+ NamedGroup[] groups;
+ if (requireFips) {
+ groups = new NamedGroup[] {
+ // only NIST curves in FIPS mode
+ NamedGroup.SECP256_R1,
+ NamedGroup.SECP384_R1,
+ NamedGroup.SECP521_R1,
+ NamedGroup.SECT283_K1,
+ NamedGroup.SECT283_R1,
+ NamedGroup.SECT409_K1,
+ NamedGroup.SECT409_R1,
+ NamedGroup.SECT571_K1,
+ NamedGroup.SECT571_R1,
+
+ // FFDHE 2048
+ NamedGroup.FFDHE_2048,
+ NamedGroup.FFDHE_3072,
+ NamedGroup.FFDHE_4096,
+ NamedGroup.FFDHE_6144,
+ NamedGroup.FFDHE_8192,
+ };
+ } else {
+ groups = new NamedGroup[] {
+ // NIST curves first
+ NamedGroup.SECP256_R1,
+ NamedGroup.SECP384_R1,
+ NamedGroup.SECP521_R1,
+ NamedGroup.SECT283_K1,
+ NamedGroup.SECT283_R1,
+ NamedGroup.SECT409_K1,
+ NamedGroup.SECT409_R1,
+ NamedGroup.SECT571_K1,
+ NamedGroup.SECT571_R1,
+
+ // non-NIST curves
+ NamedGroup.SECP256_K1,
+
+ // FFDHE 2048
+ NamedGroup.FFDHE_2048,
+ NamedGroup.FFDHE_3072,
+ NamedGroup.FFDHE_4096,
+ NamedGroup.FFDHE_6144,
+ NamedGroup.FFDHE_8192,
+ };
+ }
+
+ groupList = new ArrayList<>(groups.length);
+ for (NamedGroup group : groups) {
+ if (isAvailableGroup(group)) {
+ groupList.add(group);
+ }
+ }
+ }
+
+ if (debug != null && groupList.isEmpty()) {
+ Debug.log(
+ "Initialized [jdk.tls.namedGroups|default] list contains " +
+ "no available elliptic curves. " +
+ (property != null ? "(" + property + ")" : "[Default]"));
+ }
+
+ supportedNamedGroups = new NamedGroup[groupList.size()];
+ int i = 0;
+ for (NamedGroup namedGroup : groupList) {
+ supportedNamedGroups[i++] = namedGroup;
+ }
+ }
+
+ // check whether the group is supported by the underlying providers
+ private static boolean isAvailableGroup(NamedGroup namedGroup) {
+ AlgorithmParameters params = null;
+ AlgorithmParameterSpec spec = null;
+ if ("EC".equals(namedGroup.algorithm)) {
+ if (namedGroup.oid != null) {
+ try {
+ params = JsseJce.getAlgorithmParameters("EC");
+ spec = new ECGenParameterSpec(namedGroup.oid);
+ } catch (Exception e) {
+ return false;
+ }
+ }
+ } else if ("DiffieHellman".equals(namedGroup.algorithm)) {
+ try {
+ params = JsseJce.getAlgorithmParameters("DiffieHellman");
+ spec = getFFDHEDHParameterSpec(namedGroup);
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ if ((params != null) && (spec != null)) {
+ try {
+ params.init(spec);
+ } catch (Exception e) {
+ return false;
+ }
+
+ // cache the parameters
+ namedGroupParams.put(namedGroup, params);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ 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;
+ }
+
+ private SupportedGroupsExtension(int[] requestedNamedGroupIds) {
+ super(ExtensionType.EXT_SUPPORTED_GROUPS);
+
+ this.requestedNamedGroupIds = requestedNamedGroupIds;
+ }
+
+ SupportedGroupsExtension(HandshakeInStream s, int len) throws IOException {
+ super(ExtensionType.EXT_SUPPORTED_GROUPS);
+
+ int k = s.getInt16();
+ if (((len & 1) != 0) || (k == 0) || (k + 2 != len)) {
+ throw new SSLProtocolException("Invalid " + type + " extension");
+ }
+
+ // Note: unknown named group will be ignored later.
+ requestedNamedGroupIds = new int[k >> 1];
+ for (int i = 0; i < requestedNamedGroupIds.length; i++) {
+ requestedNamedGroupIds[i] = s.getInt16();
+ }
+ }
+
+ // Get a local preferred supported ECDHE group permitted by the constraints.
+ static NamedGroup getPreferredECGroup(AlgorithmConstraints constraints) {
+ for (NamedGroup namedGroup : supportedNamedGroups) {
+ if ((namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) &&
+ constraints.permits(EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+ namedGroup.algorithm, namedGroupParams.get(namedGroup))) {
+
+ return namedGroup;
+ }
+ }
+
+ return null;
+ }
+
+ // Is there any supported group permitted by the constraints?
+ static boolean isActivatable(
+ AlgorithmConstraints constraints, NamedGroupType type) {
+
+ boolean hasFFDHEGroups = false;
+ for (NamedGroup namedGroup : supportedNamedGroups) {
+ if (namedGroup.type == type) {
+ if (constraints.permits(
+ EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+ namedGroup.algorithm,
+ namedGroupParams.get(namedGroup))) {
+
+ return true;
+ }
+
+ if (!hasFFDHEGroups &&
+ (type == NamedGroupType.NAMED_GROUP_FFDHE)) {
+
+ hasFFDHEGroups = true;
+ }
+ }
+ }
+
+ // For compatibility, if no FFDHE groups are defined, the non-FFDHE
+ // compatible mode (using DHE cipher suite without FFDHE extension)
+ // is allowed.
+ //
+ // Note that the constraints checking on DHE parameters will be
+ // performed during key exchanging in a handshake.
+ if (!hasFFDHEGroups && (type == NamedGroupType.NAMED_GROUP_FFDHE)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ // Create the default supported groups extension.
+ static SupportedGroupsExtension createExtension(
+ AlgorithmConstraints constraints,
+ CipherSuiteList cipherSuites, boolean enableFFDHE) {
+
+ ArrayList<Integer> groupList =
+ new ArrayList<>(supportedNamedGroups.length);
+ for (NamedGroup namedGroup : supportedNamedGroups) {
+ if ((!enableFFDHE) &&
+ (namedGroup.type == NamedGroupType.NAMED_GROUP_FFDHE)) {
+ continue;
+ }
+
+ if (cipherSuites.contains(namedGroup.type) &&
+ constraints.permits(EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+ namedGroup.algorithm, namedGroupParams.get(namedGroup))) {
+
+ groupList.add(namedGroup.id);
+ }
+ }
+
+ if (!groupList.isEmpty()) {
+ int[] ids = new int[groupList.size()];
+ int i = 0;
+ for (Integer id : groupList) {
+ ids[i++] = id;
+ }
+
+ return new SupportedGroupsExtension(ids);
+ }
+
+ return null;
+ }
+
+ // get the preferred activated named group
+ NamedGroup getPreferredGroup(
+ AlgorithmConstraints constraints, NamedGroupType type) {
+
+ for (int groupId : requestedNamedGroupIds) {
+ NamedGroup namedGroup = NamedGroup.valueOf(groupId);
+ if ((namedGroup != null) && (namedGroup.type == type) &&
+ SupportedGroupsExtension.supports(namedGroup) &&
+ constraints.permits(EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+ namedGroup.algorithm, namedGroupParams.get(namedGroup))) {
+
+ return namedGroup;
+ }
+ }
+
+ return null;
+ }
+
+ boolean hasFFDHEGroup() {
+ for (int groupId : requestedNamedGroupIds) {
+ /*
+ * [RFC 7919] Codepoints in the "Supported Groups Registry"
+ * with a high byte of 0x01 (that is, between 256 and 511,
+ * inclusive) are set aside for FFDHE groups.
+ */
+ if ((groupId >= 256) && (groupId <= 511)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ boolean contains(int index) {
+ for (int groupId : requestedNamedGroupIds) {
+ if (index == groupId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ int length() {
+ return 6 + (requestedNamedGroupIds.length << 1);
+ }
+
+ @Override
+ void send(HandshakeOutStream s) throws IOException {
+ s.putInt16(type.id);
+ int k = requestedNamedGroupIds.length << 1;
+ s.putInt16(k + 2);
+ s.putInt16(k);
+ for (int groupId : requestedNamedGroupIds) {
+ s.putInt16(groupId);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Extension " + type + ", group names: {");
+ boolean first = true;
+ for (int groupId : requestedNamedGroupIds) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ // first check if it is a known named group, then try other cases.
+ NamedGroup namedGroup = NamedGroup.valueOf(groupId);
+ if (namedGroup != null) {
+ sb.append(namedGroup.name);
+ } else if (groupId == ARBITRARY_PRIME) {
+ sb.append("arbitrary_explicit_prime_curves");
+ } else if (groupId == ARBITRARY_CHAR2) {
+ sb.append("arbitrary_explicit_char2_curves");
+ } else {
+ sb.append("unknown named group " + groupId);
+ }
+ }
+ sb.append("}");
+ return sb.toString();
+ }
+
+ static boolean supports(NamedGroup namedGroup) {
+ for (NamedGroup group : supportedNamedGroups) {
+ if (namedGroup.id == group.id) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ static ECGenParameterSpec getECGenParamSpec(NamedGroup namedGroup) {
+ if (namedGroup.type != NamedGroupType.NAMED_GROUP_ECDHE) {
+ throw new RuntimeException("Not a named EC group: " + namedGroup);
+ }
+
+ AlgorithmParameters params = namedGroupParams.get(namedGroup);
+ try {
+ return params.getParameterSpec(ECGenParameterSpec.class);
+ } catch (InvalidParameterSpecException ipse) {
+ // should be unlikely
+ return new ECGenParameterSpec(namedGroup.oid);
+ }
+ }
+
+ static DHParameterSpec getDHParameterSpec(NamedGroup namedGroup) {
+ if (namedGroup.type != NamedGroupType.NAMED_GROUP_FFDHE) {
+ throw new RuntimeException("Not a named DH group: " + namedGroup);
+ }
+
+ AlgorithmParameters params = namedGroupParams.get(namedGroup);
+ try {
+ return params.getParameterSpec(DHParameterSpec.class);
+ } catch (InvalidParameterSpecException ipse) {
+ // should be unlikely
+ return getPredefinedDHParameterSpec(namedGroup);
+ }
+ }
+}
--- a/jdk/test/sun/security/ssl/DHKeyExchange/DHEKeySizing.java Thu May 11 07:33:23 2017 +0800
+++ b/jdk/test/sun/security/ssl/DHKeyExchange/DHEKeySizing.java Wed May 10 23:40:46 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,33 +31,44 @@
* @bug 6956398
* @summary make ephemeral DH key match the length of the certificate key
* @run main/othervm
+ * DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA false 1639 267
+ * @run main/othervm -Djsse.enableFFDHE=false
* DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1255 75
- * @run main/othervm -Djdk.tls.ephemeralDHKeySize=matched
+ * @run main/othervm -Djsse.enableFFDHE=false
+ * -Djdk.tls.ephemeralDHKeySize=matched
* DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1255 75
- * @run main/othervm -Djdk.tls.ephemeralDHKeySize=legacy
+ * @run main/othervm -Djsse.enableFFDHE=false
+ * -Djdk.tls.ephemeralDHKeySize=legacy
* DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1255 75
- * @run main/othervm -Djdk.tls.ephemeralDHKeySize=1024
+ * @run main/othervm -Djsse.enableFFDHE=false
+ * -Djdk.tls.ephemeralDHKeySize=1024
* DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1255 75
*
- * @run main/othervm
+ * @run main/othervm -Djsse.enableFFDHE=false
* DHEKeySizing SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA true 229 75
*
- * @run main/othervm
+ * @run main/othervm -Djsse.enableFFDHE=false
* DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA false 1383 139
- * @run main/othervm -Djdk.tls.ephemeralDHKeySize=legacy
+ * @run main/othervm -Djsse.enableFFDHE=false
+ * -Djdk.tls.ephemeralDHKeySize=legacy
* DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA false 1319 107
- * @run main/othervm -Djdk.tls.ephemeralDHKeySize=matched
+ * @run main/othervm -Djsse.enableFFDHE=false
+ * -Djdk.tls.ephemeralDHKeySize=matched
* DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA false 1639 267
- * @run main/othervm -Djdk.tls.ephemeralDHKeySize=1024
+ * @run main/othervm -Djsse.enableFFDHE=false
+ * -Djdk.tls.ephemeralDHKeySize=1024
* DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA false 1383 139
*
- * @run main/othervm
+ * @run main/othervm -Djsse.enableFFDHE=false
* DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5 false 357 139
- * @run main/othervm -Djdk.tls.ephemeralDHKeySize=legacy
+ * @run main/othervm -Djsse.enableFFDHE=false
+ * -Djdk.tls.ephemeralDHKeySize=legacy
* DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5 false 293 107
- * @run main/othervm -Djdk.tls.ephemeralDHKeySize=matched
+ * @run main/othervm -Djsse.enableFFDHE=false
+ * -Djdk.tls.ephemeralDHKeySize=matched
* DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5 false 357 139
- * @run main/othervm -Djdk.tls.ephemeralDHKeySize=1024
+ * @run main/othervm -Djsse.enableFFDHE=false
+ * -Djdk.tls.ephemeralDHKeySize=1024
* DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5 false 357 139
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/DHKeyExchange/UseStrongDHSizes.java Wed May 10 23:40:46 2017 +0000
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+//
+
+/*
+ * @test
+ * @bug 8140436
+ * @modules jdk.crypto.ec
+ * @library /javax/net/ssl/templates
+ * @summary Negotiated Finite Field Diffie-Hellman Ephemeral Parameters for TLS
+ * @run main/othervm UseStrongDHSizes 2048
+ */
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.Security;
+import javax.net.ssl.SSLSocket;
+
+public class UseStrongDHSizes extends SSLSocketTemplate {
+ /*
+ * Run the test case.
+ */
+ public static void main(String[] args) throws Exception {
+ // reset the security property to make sure that the algorithms
+ // and keys used in this test are not disabled unexpectedly.
+ String constraint = "DH keySize < " + Integer.valueOf(args[0]);
+ Security.setProperty("jdk.tls.disabledAlgorithms", constraint);
+ Security.setProperty("jdk.certpath.disabledAlgorithms", "");
+
+ (new UseStrongDHSizes()).run();
+ }
+
+ @Override
+ protected void runServerApplication(SSLSocket socket) throws Exception {
+ String ciphers[] = {
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+ "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"};
+
+ socket.setEnabledCipherSuites(ciphers);
+ socket.setWantClientAuth(true);
+
+ InputStream sslIS = socket.getInputStream();
+ OutputStream sslOS = socket.getOutputStream();
+
+ sslIS.read();
+ sslOS.write(85);
+ sslOS.flush();
+ }
+
+ @Override
+ protected void runClientApplication(SSLSocket socket) throws Exception {
+ String ciphers[] = {
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+ "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"};
+ socket.setEnabledCipherSuites(ciphers);
+ socket.setUseClientMode(true);
+
+ InputStream sslIS = socket.getInputStream();
+ OutputStream sslOS = socket.getOutputStream();
+
+ sslOS.write(280);
+ sslOS.flush();
+ sslIS.read();
+ }
+}