--- a/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java Thu Aug 30 09:08:23 2018 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java Thu Aug 30 11:08:01 2018 -0400
@@ -61,7 +61,7 @@
static final SSLKeyAgreementGenerator kaGenerator =
new DHEKAGenerator();
- static final class DHECredentials implements SSLCredentials {
+ static final class DHECredentials implements SSLKeyAgreementCredentials {
final DHPublicKey popPublicKey;
final NamedGroup namedGroup;
@@ -70,6 +70,11 @@
this.namedGroup = namedGroup;
}
+ @Override
+ public PublicKey getPublicKey() {
+ return popPublicKey;
+ }
+
static DHECredentials valueOf(NamedGroup ng,
byte[] encodedPublic) throws IOException, GeneralSecurityException {
@@ -401,7 +406,7 @@
@Override
public SSLKeyDerivation createKeyDerivation(
- HandshakeContext context) throws IOException {
+ HandshakeContext context) throws IOException {
DHEPossession dhePossession = null;
DHECredentials dheCredentials = null;
for (SSLPossession poss : context.handshakePossessions) {
@@ -424,7 +429,7 @@
DHParameterSpec pps = dhep.publicKey.getParams();
DHParameterSpec cps = dhec.popPublicKey.getParams();
if (pps.getP().equals(cps.getP()) &&
- pps.getG().equals(cps.getG())) {
+ pps.getG().equals(cps.getG())) {
dheCredentials = (DHECredentials)cred;
break;
}
@@ -439,96 +444,11 @@
if (dhePossession == null || dheCredentials == null) {
context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
- "No sufficient DHE key agreement parameters negotiated");
- }
-
- return new DHEKAKeyDerivation(context,
- dhePossession.privateKey, dheCredentials.popPublicKey);
- }
-
- private static final
- class DHEKAKeyDerivation implements SSLKeyDerivation {
- private final HandshakeContext context;
- private final PrivateKey localPrivateKey;
- private final PublicKey peerPublicKey;
-
- DHEKAKeyDerivation(HandshakeContext context,
- PrivateKey localPrivateKey,
- PublicKey peerPublicKey) {
- this.context = context;
- this.localPrivateKey = localPrivateKey;
- this.peerPublicKey = peerPublicKey;
- }
-
- @Override
- public SecretKey deriveKey(String algorithm,
- AlgorithmParameterSpec params) throws IOException {
- if (!context.negotiatedProtocol.useTLS13PlusSpec()) {
- return t12DeriveKey(algorithm, params);
- } else {
- return t13DeriveKey(algorithm, params);
- }
+ "No sufficient DHE key agreement parameters negotiated");
}
- private SecretKey t12DeriveKey(String algorithm,
- AlgorithmParameterSpec params) throws IOException {
- try {
- KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman");
- ka.init(localPrivateKey);
- ka.doPhase(peerPublicKey, true);
- SecretKey preMasterSecret =
- ka.generateSecret("TlsPremasterSecret");
- SSLMasterKeyDerivation mskd =
- SSLMasterKeyDerivation.valueOf(
- context.negotiatedProtocol);
- if (mskd == null) {
- // unlikely
- throw new SSLHandshakeException(
- "No expected master key derivation for protocol: " +
- context.negotiatedProtocol.name);
- }
- SSLKeyDerivation kd = mskd.createKeyDerivation(
- context, preMasterSecret);
- return kd.deriveKey("MasterSecret", params);
- } catch (GeneralSecurityException gse) {
- throw (SSLHandshakeException) new SSLHandshakeException(
- "Could not generate secret").initCause(gse);
- }
- }
-
- private SecretKey t13DeriveKey(String algorithm,
- AlgorithmParameterSpec params) throws IOException {
- try {
- KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman");
- ka.init(localPrivateKey);
- ka.doPhase(peerPublicKey, true);
- SecretKey sharedSecret =
- ka.generateSecret("TlsPremasterSecret");
-
- HashAlg hashAlg = context.negotiatedCipherSuite.hashAlg;
- SSLKeyDerivation kd = context.handshakeKeyDerivation;
- HKDF hkdf = new HKDF(hashAlg.name);
- if (kd == null) { // No PSK is in use.
- // If PSK is not in use Early Secret will still be
- // HKDF-Extract(0, 0).
- byte[] zeros = new byte[hashAlg.hashLength];
- SecretKeySpec ikm =
- new SecretKeySpec(zeros, "TlsPreSharedSecret");
- SecretKey earlySecret =
- hkdf.extract(zeros, ikm, "TlsEarlySecret");
- kd = new SSLSecretDerivation(context, earlySecret);
- }
-
- // derive salt secret
- SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
-
- // derive handshake secret
- return hkdf.extract(saltSecret, sharedSecret, algorithm);
- } catch (GeneralSecurityException gse) {
- throw (SSLHandshakeException) new SSLHandshakeException(
- "Could not generate secret").initCause(gse);
- }
- }
+ return new KAKeyDerivation("DiffieHellman", context,
+ dhePossession.privateKey, dheCredentials.popPublicKey);
}
}
}
--- a/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java Thu Aug 30 09:08:23 2018 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java Thu Aug 30 11:08:01 2018 -0400
@@ -63,7 +63,7 @@
static final SSLKeyAgreementGenerator ecdhKAGenerator =
new ECDHKAGenerator();
- static final class ECDHECredentials implements SSLCredentials {
+ static final class ECDHECredentials implements SSLKeyAgreementCredentials {
final ECPublicKey popPublicKey;
final NamedGroup namedGroup;
@@ -72,6 +72,11 @@
this.namedGroup = namedGroup;
}
+ @Override
+ public PublicKey getPublicKey() {
+ return popPublicKey;
+ }
+
static ECDHECredentials valueOf(NamedGroup namedGroup,
byte[] encodedPoint) throws IOException, GeneralSecurityException {
@@ -299,7 +304,7 @@
"No sufficient ECDHE key agreement parameters negotiated");
}
- return new ECDHEKAKeyDerivation(shc,
+ return new KAKeyDerivation("ECDH", shc,
x509Possession.popPrivateKey, ecdheCredentials.popPublicKey);
}
@@ -348,7 +353,7 @@
"No sufficient ECDH key agreement parameters negotiated");
}
- return new ECDHEKAKeyDerivation(chc,
+ return new KAKeyDerivation("ECDH", chc,
ecdhePossession.privateKey, x509Credentials.popPublicKey);
}
}
@@ -392,94 +397,8 @@
"No sufficient ECDHE key agreement parameters negotiated");
}
- return new ECDHEKAKeyDerivation(context,
+ return new KAKeyDerivation("ECDH", context,
ecdhePossession.privateKey, ecdheCredentials.popPublicKey);
}
}
-
- private static final
- class ECDHEKAKeyDerivation implements SSLKeyDerivation {
- private final HandshakeContext context;
- private final PrivateKey localPrivateKey;
- private final PublicKey peerPublicKey;
-
- ECDHEKAKeyDerivation(HandshakeContext context,
- PrivateKey localPrivateKey,
- PublicKey peerPublicKey) {
- this.context = context;
- this.localPrivateKey = localPrivateKey;
- this.peerPublicKey = peerPublicKey;
- }
-
- @Override
- public SecretKey deriveKey(String algorithm,
- AlgorithmParameterSpec params) throws IOException {
- if (!context.negotiatedProtocol.useTLS13PlusSpec()) {
- return t12DeriveKey(algorithm, params);
- } else {
- return t13DeriveKey(algorithm, params);
- }
- }
-
- private SecretKey t12DeriveKey(String algorithm,
- AlgorithmParameterSpec params) throws IOException {
- try {
- KeyAgreement ka = JsseJce.getKeyAgreement("ECDH");
- ka.init(localPrivateKey);
- ka.doPhase(peerPublicKey, true);
- SecretKey preMasterSecret =
- ka.generateSecret("TlsPremasterSecret");
-
- SSLMasterKeyDerivation mskd =
- SSLMasterKeyDerivation.valueOf(
- context.negotiatedProtocol);
- if (mskd == null) {
- // unlikely
- throw new SSLHandshakeException(
- "No expected master key derivation for protocol: " +
- context.negotiatedProtocol.name);
- }
- SSLKeyDerivation kd = mskd.createKeyDerivation(
- context, preMasterSecret);
- return kd.deriveKey("MasterSecret", params);
- } catch (GeneralSecurityException gse) {
- throw (SSLHandshakeException) new SSLHandshakeException(
- "Could not generate secret").initCause(gse);
- }
- }
-
- private SecretKey t13DeriveKey(String algorithm,
- AlgorithmParameterSpec params) throws IOException {
- try {
- KeyAgreement ka = JsseJce.getKeyAgreement("ECDH");
- ka.init(localPrivateKey);
- ka.doPhase(peerPublicKey, true);
- SecretKey sharedSecret =
- ka.generateSecret("TlsPremasterSecret");
-
- HashAlg hashAlg = context.negotiatedCipherSuite.hashAlg;
- SSLKeyDerivation kd = context.handshakeKeyDerivation;
- HKDF hkdf = new HKDF(hashAlg.name);
- if (kd == null) { // No PSK is in use.
- // If PSK is not in use Early Secret will still be
- // HKDF-Extract(0, 0).
- byte[] zeros = new byte[hashAlg.hashLength];
- SecretKeySpec ikm =
- new SecretKeySpec(zeros, "TlsPreSharedSecret");
- SecretKey earlySecret =
- hkdf.extract(zeros, ikm, "TlsEarlySecret");
- kd = new SSLSecretDerivation(context, earlySecret);
- }
-
- // derive salt secret
- SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
-
- // derive handshake secret
- return hkdf.extract(saltSecret, sharedSecret, algorithm);
- } catch (GeneralSecurityException gse) {
- throw (SSLHandshakeException) new SSLHandshakeException(
- "Could not generate secret").initCause(gse);
- }
- }
- }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/KAKeyDerivation.java Thu Aug 30 11:08:01 2018 -0400
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2018, 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 javax.crypto.KeyAgreement;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import javax.net.ssl.SSLHandshakeException;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+
+public class KAKeyDerivation implements SSLKeyDerivation {
+
+ private final String algorithmName;
+ private final HandshakeContext context;
+ private final PrivateKey localPrivateKey;
+ private final PublicKey peerPublicKey;
+
+ KAKeyDerivation(String algorithmName,
+ HandshakeContext context,
+ PrivateKey localPrivateKey,
+ PublicKey peerPublicKey) {
+ this.algorithmName = algorithmName;
+ this.context = context;
+ this.localPrivateKey = localPrivateKey;
+ this.peerPublicKey = peerPublicKey;
+ }
+
+ @Override
+ public
+ SecretKey deriveKey(String algorithm,
+ AlgorithmParameterSpec params) throws IOException {
+ if (!context.negotiatedProtocol.useTLS13PlusSpec()) {
+ return t12DeriveKey(algorithm, params);
+ } else {
+ return t13DeriveKey(algorithm, params);
+ }
+ }
+
+ private
+ SecretKey t12DeriveKey(String algorithm,
+ AlgorithmParameterSpec params) throws IOException {
+ try {
+ KeyAgreement ka = JsseJce.getKeyAgreement(algorithmName);
+ ka.init(localPrivateKey);
+ ka.doPhase(peerPublicKey, true);
+ SecretKey preMasterSecret =
+ ka.generateSecret("TlsPremasterSecret");
+ SSLMasterKeyDerivation mskd =
+ SSLMasterKeyDerivation.valueOf(
+ context.negotiatedProtocol);
+ if (mskd == null) {
+ // unlikely
+ throw new SSLHandshakeException(
+ "No expected master key derivation for protocol: " +
+ context.negotiatedProtocol.name);
+ }
+ SSLKeyDerivation kd = mskd.createKeyDerivation(
+ context, preMasterSecret);
+ return kd.deriveKey("MasterSecret", params);
+ } catch (GeneralSecurityException gse) {
+ throw (SSLHandshakeException) new SSLHandshakeException(
+ "Could not generate secret").initCause(gse);
+ }
+ }
+
+ private
+ SecretKey t13DeriveKey(String algorithm,
+ AlgorithmParameterSpec params) throws IOException {
+ try {
+ KeyAgreement ka = JsseJce.getKeyAgreement(algorithmName);
+ ka.init(localPrivateKey);
+ ka.doPhase(peerPublicKey, true);
+ SecretKey sharedSecret =
+ ka.generateSecret("TlsPremasterSecret");
+
+ CipherSuite.HashAlg hashAlg = context.negotiatedCipherSuite.hashAlg;
+ SSLKeyDerivation kd = context.handshakeKeyDerivation;
+ HKDF hkdf = new HKDF(hashAlg.name);
+ if (kd == null) { // No PSK is in use.
+ // If PSK is not in use Early Secret will still be
+ // HKDF-Extract(0, 0).
+ byte[] zeros = new byte[hashAlg.hashLength];
+ SecretKeySpec ikm =
+ new SecretKeySpec(zeros, "TlsPreSharedSecret");
+ SecretKey earlySecret =
+ hkdf.extract(zeros, ikm, "TlsEarlySecret");
+ kd = new SSLSecretDerivation(context, earlySecret);
+ }
+
+ // derive salt secret
+ SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
+
+ // derive handshake secret
+ return hkdf.extract(saltSecret, sharedSecret, algorithm);
+ } catch (GeneralSecurityException gse) {
+ throw (SSLHandshakeException) new SSLHandshakeException(
+ "Could not generate secret").initCause(gse);
+ }
+ }
+}
--- a/src/java.base/share/classes/sun/security/ssl/KeyShareExtension.java Thu Aug 30 09:08:23 2018 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/KeyShareExtension.java Thu Aug 30 11:08:01 2018 -0400
@@ -42,12 +42,14 @@
import sun.security.ssl.DHKeyExchange.DHEPossession;
import sun.security.ssl.ECDHKeyExchange.ECDHECredentials;
import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
+import sun.security.ssl.XDHKeyExchange.XDHEPossession;
+import sun.security.ssl.XDHKeyExchange.XDHECredentials;
import sun.security.ssl.KeyShareExtension.CHKeyShareSpec;
import sun.security.ssl.SSLExtension.ExtensionConsumer;
import sun.security.ssl.SSLExtension.SSLExtensionSpec;
import sun.security.ssl.SSLHandshake.HandshakeMessage;
import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
+import sun.security.ssl.SupportedGroupsExtension.NamedGroupFunctions;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
import sun.security.util.HexDumpEncoder;
@@ -265,7 +267,8 @@
// update the context
chc.handshakePossessions.add(pos);
if (!(pos instanceof ECDHEPossession) &&
- !(pos instanceof DHEPossession)) {
+ !(pos instanceof DHEPossession) &&
+ !(pos instanceof XDHEPossession)) {
// May need more possesion types in the future.
continue;
}
@@ -354,46 +357,26 @@
continue;
}
- if (ng.type == NamedGroupType.NAMED_GROUP_ECDHE) {
- try {
- ECDHECredentials ecdhec =
- ECDHECredentials.valueOf(ng, entry.keyExchange);
- if (ecdhec != null) {
- if (!shc.algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- ecdhec.popPublicKey)) {
- SSLLogger.warning(
- "ECDHE key share entry does not " +
- "comply to algorithm constraints");
- } else {
- credentials.add(ecdhec);
- }
+ try {
+ NamedGroupFunctions ngf = ng.getFunctions().orElseThrow(
+ GeneralSecurityException::new);
+ SSLKeyAgreementCredentials kaCred =
+ ngf.decodeCredentials(entry.keyExchange);
+ if (kaCred != null) {
+ if (!shc.algorithmConstraints.permits(
+ EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+ kaCred.getPublicKey())) {
+ SSLLogger.warning(
+ "key share entry does not " +
+ "comply with algorithm constraints");
+ } else {
+ credentials.add(kaCred);
}
- } catch (IOException | GeneralSecurityException ex) {
- SSLLogger.warning(
- "Cannot decode named group: " +
- NamedGroup.nameOf(entry.namedGroupId));
}
- } else if (ng.type == NamedGroupType.NAMED_GROUP_FFDHE) {
- try {
- DHECredentials dhec =
- DHECredentials.valueOf(ng, entry.keyExchange);
- if (dhec != null) {
- if (!shc.algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- dhec.popPublicKey)) {
- SSLLogger.warning(
- "DHE key share entry does not " +
- "comply to algorithm constraints");
- } else {
- credentials.add(dhec);
- }
- }
- } catch (IOException | GeneralSecurityException ex) {
- SSLLogger.warning(
- "Cannot decode named group: " +
- NamedGroup.nameOf(entry.namedGroupId));
- }
+ } catch (GeneralSecurityException ex) {
+ SSLLogger.warning(
+ "Cannot decode named group: " +
+ NamedGroup.nameOf(entry.namedGroupId));
}
}
@@ -531,6 +514,8 @@
ng = ((ECDHECredentials)cd).namedGroup;
} else if (cd instanceof DHECredentials) {
ng = ((DHECredentials)cd).namedGroup;
+ } else if (cd instanceof XDHECredentials) {
+ ng = ((XDHECredentials)cd).namedGroup;
}
if (ng == null) {
@@ -549,7 +534,8 @@
SSLPossession[] poses = ke.createPossessions(shc);
for (SSLPossession pos : poses) {
if (!(pos instanceof ECDHEPossession) &&
- !(pos instanceof DHEPossession)) {
+ !(pos instanceof DHEPossession) &&
+ !(pos instanceof XDHEPossession)) {
// May need more possesion types in the future.
continue;
}
@@ -649,50 +635,26 @@
}
SSLCredentials credentials = null;
- if (ng.type == NamedGroupType.NAMED_GROUP_ECDHE) {
- try {
- ECDHECredentials ecdhec =
- ECDHECredentials.valueOf(ng, keyShare.keyExchange);
- if (ecdhec != null) {
- if (!chc.algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- ecdhec.popPublicKey)) {
- chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
- "ECDHE key share entry does not " +
- "comply to algorithm constraints");
- } else {
- credentials = ecdhec;
- }
+ try {
+ NamedGroupFunctions ngf = ng.getFunctions().orElseThrow(
+ GeneralSecurityException::new);
+ SSLKeyAgreementCredentials kaCred =
+ ngf.decodeCredentials(keyShare.keyExchange);
+ if (kaCred != null) {
+ if (!chc.algorithmConstraints.permits(
+ EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+ kaCred.getPublicKey())) {
+ chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
+ "key share entry does not " +
+ "comply to algorithm constraints");
+ } else {
+ credentials = kaCred;
}
- } catch (IOException | GeneralSecurityException ex) {
- chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
- "Cannot decode named group: " +
- NamedGroup.nameOf(keyShare.namedGroupId));
}
- } else if (ng.type == NamedGroupType.NAMED_GROUP_FFDHE) {
- try {
- DHECredentials dhec =
- DHECredentials.valueOf(ng, keyShare.keyExchange);
- if (dhec != null) {
- if (!chc.algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- dhec.popPublicKey)) {
- chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
- "DHE key share entry does not " +
- "comply to algorithm constraints");
- } else {
- credentials = dhec;
- }
- }
- } catch (IOException | GeneralSecurityException ex) {
- chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
- "Cannot decode named group: " +
- NamedGroup.nameOf(keyShare.namedGroupId));
- }
- } else {
+ } catch (IOException | GeneralSecurityException ex) {
chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
- "Unsupported named group: " +
- NamedGroup.nameOf(keyShare.namedGroupId));
+ "Cannot decode named group: " +
+ NamedGroup.nameOf(keyShare.namedGroupId));
}
if (credentials == null) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/SSLKeyAgreementCredentials.java Thu Aug 30 11:08:01 2018 -0400
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018, 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.PublicKey;
+
+interface SSLKeyAgreementCredentials extends SSLCredentials {
+
+ PublicKey getPublicKey();
+}
--- a/src/java.base/share/classes/sun/security/ssl/SSLKeyExchange.java Thu Aug 30 09:08:23 2018 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/SSLKeyExchange.java Thu Aug 30 11:08:01 2018 -0400
@@ -30,10 +30,9 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
-import sun.security.ssl.DHKeyExchange.DHEPossession;
-import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
+import java.util.Optional;
import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
+import sun.security.ssl.SupportedGroupsExtension.NamedGroupFunctions;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
import sun.security.ssl.X509Authentication.X509Possession;
@@ -570,27 +569,24 @@
@Override
public SSLPossession createPossession(HandshakeContext hc) {
- if (namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) {
- return new ECDHEPossession(
- namedGroup, hc.sslContext.getSecureRandom());
- } else if (namedGroup.type == NamedGroupType.NAMED_GROUP_FFDHE) {
- return new DHEPossession(
- namedGroup, hc.sslContext.getSecureRandom());
+
+ Optional<NamedGroupFunctions> ngf = namedGroup.getFunctions();
+ if (ngf.isEmpty()) {
+ return null;
}
-
- return null;
+ return ngf.get().createPossession(hc.sslContext.getSecureRandom());
}
@Override
public SSLKeyDerivation createKeyDerivation(
HandshakeContext hc) throws IOException {
- if (namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) {
- return ECDHKeyExchange.ecdheKAGenerator.createKeyDerivation(hc);
- } else if (namedGroup.type == NamedGroupType.NAMED_GROUP_FFDHE) {
- return DHKeyExchange.kaGenerator.createKeyDerivation(hc);
+
+ Optional<NamedGroupFunctions> ngf = namedGroup.getFunctions();
+ if (ngf.isEmpty()) {
+ return null;
}
+ return ngf.get().createKeyDerivation(hc);
- return null;
}
}
}
--- a/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java Thu Aug 30 09:08:23 2018 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java Thu Aug 30 11:08:01 2018 -0400
@@ -31,20 +31,24 @@
import java.security.AlgorithmConstraints;
import java.security.AlgorithmParameters;
import java.security.CryptoPrimitive;
+import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.NamedParameterSpec;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
-import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Optional;
import javax.crypto.spec.DHParameterSpec;
import javax.net.ssl.SSLProtocolException;
import sun.security.action.GetPropertyAction;
@@ -158,7 +162,7 @@
}
}
- static enum NamedGroupType {
+ enum NamedGroupType {
NAMED_GROUP_ECDHE, // Elliptic Curve Groups (ECDHE)
NAMED_GROUP_FFDHE, // Finite Field Groups (DHE)
NAMED_GROUP_XDH, // Finite Field Groups (XDH)
@@ -176,6 +180,264 @@
}
}
+ public static abstract class NamedGroupFunctions {
+
+ // cache to speed up the parameters construction
+ protected static final Map<NamedGroup, AlgorithmParameters>
+ namedGroupParams = new ConcurrentHashMap<>();
+
+ private final NamedGroup ng;
+
+ protected NamedGroupFunctions(NamedGroup ng) {
+ this.ng = ng;
+ }
+
+ public AlgorithmParameters getParameters() {
+
+ AlgorithmParameters result = namedGroupParams.get(ng);
+ if (result == null) {
+ Optional<AlgorithmParameters> paramsOpt = getParametersImpl();
+ if (paramsOpt.isPresent()) {
+ result = paramsOpt.get();
+ namedGroupParams.put(ng, result);
+ }
+ }
+
+ return result;
+ }
+
+ public NamedGroup getNamedGroup() {
+ return ng;
+ }
+
+ public abstract
+ SSLKeyAgreementCredentials decodeCredentials(byte[] encoded)
+ throws IOException, GeneralSecurityException;
+
+ public abstract SSLPossession createPossession(SecureRandom random);
+
+ public abstract
+ SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
+ throws IOException;
+
+ protected abstract Optional<AlgorithmParameters> getParametersImpl();
+ public abstract AlgorithmParameterSpec getParameterSpec();
+
+ public abstract boolean isAvailable();
+ }
+
+ private static class FFDHFunctions extends NamedGroupFunctions {
+
+
+ FFDHFunctions(NamedGroup ng) {
+ super(ng);
+ }
+
+ @Override
+ public SSLKeyAgreementCredentials decodeCredentials(byte[] encoded)
+ throws IOException, GeneralSecurityException {
+ return DHKeyExchange.DHECredentials.valueOf(getNamedGroup(),
+ encoded);
+ }
+
+ @Override
+ public SSLPossession createPossession(SecureRandom random) {
+ return new DHKeyExchange.DHEPossession(getNamedGroup(), random);
+ }
+
+ @Override
+ public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
+ throws IOException {
+ return DHKeyExchange.kaGenerator.createKeyDerivation(hc);
+ }
+
+ @Override
+ public AlgorithmParameterSpec getParameterSpec() {
+ return getDHParameterSpec();
+ }
+
+ DHParameterSpec getDHParameterSpec() {
+
+ AlgorithmParameters params = getParameters();
+ try {
+ return params.getParameterSpec(DHParameterSpec.class);
+ } catch (InvalidParameterSpecException ipse) {
+ // should be unlikely
+ return getPredefinedDHParameterSpec(getNamedGroup());
+ }
+ }
+
+ private static DHParameterSpec getFFDHEDHParameterSpec(
+ NamedGroup namedGroup) {
+
+ DHParameterSpec spec = null;
+ switch (namedGroup) {
+ case FFDHE_2048:
+ spec = PredefinedDHParameterSpecs.ffdheParams.get(2048);
+ break;
+ case FFDHE_3072:
+ spec = PredefinedDHParameterSpecs.ffdheParams.get(3072);
+ break;
+ case FFDHE_4096:
+ spec = PredefinedDHParameterSpecs.ffdheParams.get(4096);
+ break;
+ case FFDHE_6144:
+ spec = PredefinedDHParameterSpecs.ffdheParams.get(6144);
+ break;
+ case FFDHE_8192:
+ spec = PredefinedDHParameterSpecs.ffdheParams.get(8192);
+ }
+
+ return spec;
+ }
+
+ private static DHParameterSpec getPredefinedDHParameterSpec(
+ NamedGroup namedGroup) {
+
+ DHParameterSpec spec = null;
+ switch (namedGroup) {
+ case FFDHE_2048:
+ spec = PredefinedDHParameterSpecs.definedParams.get(2048);
+ break;
+ case FFDHE_3072:
+ spec = PredefinedDHParameterSpecs.definedParams.get(3072);
+ break;
+ case FFDHE_4096:
+ spec = PredefinedDHParameterSpecs.definedParams.get(4096);
+ break;
+ case FFDHE_6144:
+ spec = PredefinedDHParameterSpecs.definedParams.get(6144);
+ break;
+ case FFDHE_8192:
+ spec = PredefinedDHParameterSpecs.definedParams.get(8192);
+ }
+
+ return spec;
+ }
+
+ @Override
+ public boolean isAvailable() {
+
+ AlgorithmParameters params = getParameters();
+ return params != null;
+ }
+
+ @Override
+ protected Optional<AlgorithmParameters> getParametersImpl() {
+ try {
+ AlgorithmParameters params =
+ JsseJce.getAlgorithmParameters("DiffieHellman");
+ AlgorithmParameterSpec spec =
+ getFFDHEDHParameterSpec(getNamedGroup());
+ params.init(spec);
+ return Optional.of(params);
+ } catch (InvalidParameterSpecException |
+ NoSuchAlgorithmException ex) {
+ return Optional.empty();
+ }
+ }
+
+ }
+
+ private static class ECDHFunctions extends NamedGroupFunctions {
+
+ ECDHFunctions(NamedGroup ng) {
+ super(ng);
+ }
+
+ @Override
+ public SSLKeyAgreementCredentials decodeCredentials(byte[] encoded)
+ throws IOException, GeneralSecurityException {
+ return ECDHKeyExchange.ECDHECredentials.valueOf(getNamedGroup(),
+ encoded);
+ }
+
+ @Override
+ public SSLPossession createPossession(SecureRandom random) {
+ return new ECDHKeyExchange.ECDHEPossession(getNamedGroup(),
+ random);
+ }
+
+ @Override
+ public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
+ throws IOException {
+ return ECDHKeyExchange.ecdheKAGenerator.createKeyDerivation(hc);
+ }
+
+ @Override
+ public AlgorithmParameterSpec getParameterSpec() {
+ return SupportedGroups.getECGenParamSpec(getNamedGroup());
+ }
+
+ @Override
+ public boolean isAvailable() {
+
+ AlgorithmParameters params = getParameters();
+ return params != null;
+ }
+
+ @Override
+ protected Optional<AlgorithmParameters> getParametersImpl() {
+ try {
+ AlgorithmParameters params =
+ JsseJce.getAlgorithmParameters("EC");
+ AlgorithmParameterSpec spec =
+ new ECGenParameterSpec(getNamedGroup().oid);
+ params.init(spec);
+ return Optional.of(params);
+ } catch (InvalidParameterSpecException |
+ NoSuchAlgorithmException ex) {
+ return Optional.empty();
+ }
+ }
+ }
+
+ private static class XDHFunctions extends NamedGroupFunctions {
+
+ XDHFunctions(NamedGroup ng) {
+ super(ng);
+ }
+
+ @Override
+ public SSLKeyAgreementCredentials decodeCredentials(byte[] encoded)
+ throws IOException, GeneralSecurityException {
+ return XDHKeyExchange.XDHECredentials.valueOf(getNamedGroup(),
+ encoded);
+ }
+
+ @Override
+ public SSLPossession createPossession(SecureRandom random) {
+ return new XDHKeyExchange.XDHEPossession(getNamedGroup(), random);
+ }
+
+ @Override
+ public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
+ throws IOException {
+ return XDHKeyExchange.xdheKAGenerator.createKeyDerivation(hc);
+ }
+
+ @Override
+ public AlgorithmParameterSpec getParameterSpec() {
+ return new NamedParameterSpec(getNamedGroup().algorithm);
+ }
+
+ @Override
+ public boolean isAvailable() {
+
+ try {
+ JsseJce.getKeyAgreement(getNamedGroup().algorithm);
+ return true;
+ } catch (NoSuchAlgorithmException ex) {
+ return false;
+ }
+ }
+
+ @Override
+ protected Optional<AlgorithmParameters> getParametersImpl() {
+ return Optional.empty();
+ }
+ }
+
static enum NamedGroup {
// Elliptic Curves (RFC 4492)
//
@@ -292,12 +554,14 @@
final String algorithm; // signature algorithm
final boolean isFips; // can be used in FIPS mode?
final ProtocolVersion[] supportedProtocols;
+ private final NamedGroupFunctions functions; // may be null
// Constructor used for Elliptic Curve Groups (ECDHE)
private NamedGroup(int id, String name, String oid, boolean isFips,
ProtocolVersion[] supportedProtocols) {
this.id = id;
this.type = NamedGroupType.NAMED_GROUP_ECDHE;
+ this.functions = new ECDHFunctions(this);
this.name = name;
this.oid = oid;
this.algorithm = "EC";
@@ -311,6 +575,7 @@
ProtocolVersion[] supportedProtocols) {
this.id = id;
this.type = NamedGroupType.NAMED_GROUP_XDH;
+ this.functions = new XDHFunctions(this);
this.name = name;
this.oid = null;
this.algorithm = algorithm;
@@ -323,6 +588,7 @@
ProtocolVersion[] supportedProtocols) {
this.id = id;
this.type = NamedGroupType.NAMED_GROUP_FFDHE;
+ this.functions = new FFDHFunctions(this);
this.name = name;
this.oid = null;
this.algorithm = "DiffieHellman";
@@ -335,6 +601,7 @@
ProtocolVersion[] supportedProtocols) {
this.id = id;
this.type = NamedGroupType.NAMED_GROUP_ARBITRARY;
+ this.functions = null;
this.name = name;
this.oid = null;
this.algorithm = "EC";
@@ -342,6 +609,10 @@
this.supportedProtocols = supportedProtocols;
}
+ Optional<NamedGroupFunctions> getFunctions() {
+ return Optional.ofNullable(functions);
+ }
+
static NamedGroup valueOf(int id) {
for (NamedGroup group : NamedGroup.values()) {
if (group.id == id) {
@@ -367,15 +638,14 @@
}
static NamedGroup valueOf(DHParameterSpec params) {
- for (Map.Entry<NamedGroup, AlgorithmParameters> me :
- SupportedGroups.namedGroupParams.entrySet()) {
- NamedGroup ng = me.getKey();
+ for (NamedGroup ng : NamedGroup.values()) {
if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) {
continue;
}
DHParameterSpec ngParams = null;
- AlgorithmParameters aps = me.getValue();
+ // functions is non-null for FFDHE type
+ AlgorithmParameters aps = ng.functions.getParameters();
try {
ngParams = aps.getParameterSpec(DHParameterSpec.class);
} catch (InvalidParameterSpecException ipse) {
@@ -446,17 +716,18 @@
// lazy loading of parameters
AlgorithmParameters getParameters() {
- return SupportedGroups.namedGroupParams.get(this);
+ if (functions == null) {
+ return null;
+ }
+ return functions.getParameters();
}
AlgorithmParameterSpec getParameterSpec() {
- if (this.type == NamedGroupType.NAMED_GROUP_ECDHE) {
- return SupportedGroups.getECGenParamSpec(this);
- } else if (this.type == NamedGroupType.NAMED_GROUP_FFDHE) {
- return SupportedGroups.getDHParameterSpec(this);
+ Optional<NamedGroupFunctions> ngf = getFunctions();
+ if (ngf.isEmpty()) {
+ return null;
}
-
- return null;
+ return ngf.get().getParameterSpec();
}
}
@@ -465,10 +736,6 @@
static final boolean enableFFDHE =
Utilities.getBooleanProperty("jsse.enableFFDHE", true);
- // cache to speed up the parameters construction
- static final Map<NamedGroup,
- AlgorithmParameters> namedGroupParams = new HashMap<>();
-
// the supported named groups
static final NamedGroup[] supportedNamedGroups;
@@ -552,6 +819,10 @@
// non-NIST curves
NamedGroup.SECP256_K1,
+ // XDH
+ NamedGroup.X25519,
+ NamedGroup.X448,
+
// FFDHE 2048
NamedGroup.FFDHE_2048,
NamedGroup.FFDHE_3072,
@@ -583,86 +854,13 @@
// check whether the group is supported by the underlying providers
private static boolean isAvailableGroup(NamedGroup namedGroup) {
- AlgorithmParameters params = null;
- AlgorithmParameterSpec spec = null;
- if (namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) {
- if (namedGroup.oid != null) {
- try {
- params = JsseJce.getAlgorithmParameters("EC");
- spec = new ECGenParameterSpec(namedGroup.oid);
- } catch (NoSuchAlgorithmException e) {
- return false;
- }
- }
- } else if (namedGroup.type == NamedGroupType.NAMED_GROUP_FFDHE) {
- try {
- params = JsseJce.getAlgorithmParameters("DiffieHellman");
- spec = getFFDHEDHParameterSpec(namedGroup);
- } catch (NoSuchAlgorithmException e) {
- return false;
- }
- } // Otherwise, unsupported.
- if ((params != null) && (spec != null)) {
- try {
- params.init(spec);
- } catch (InvalidParameterSpecException e) {
- return false;
- }
-
- // cache the parameters
- namedGroupParams.put(namedGroup, params);
-
- return true;
+ Optional<NamedGroupFunctions> ngfOpt = namedGroup.getFunctions();
+ if (ngfOpt.isEmpty()) {
+ return false;
}
-
- 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;
+ NamedGroupFunctions ngf = ngfOpt.get();
+ return ngf.isAvailable();
}
static ECGenParameterSpec getECGenParamSpec(NamedGroup namedGroup) {
@@ -671,7 +869,8 @@
"Not a named EC group: " + namedGroup);
}
- AlgorithmParameters params = namedGroupParams.get(namedGroup);
+ // functions is non-null for ECDHE type
+ AlgorithmParameters params = namedGroup.functions.getParameters();
try {
return params.getParameterSpec(ECGenParameterSpec.class);
} catch (InvalidParameterSpecException ipse) {
@@ -680,19 +879,12 @@
}
}
- static DHParameterSpec getDHParameterSpec(NamedGroup namedGroup) {
- if (namedGroup.type != NamedGroupType.NAMED_GROUP_FFDHE) {
- throw new RuntimeException(
- "Not a named DH group: " + namedGroup);
+ static AlgorithmParameters getParameters(NamedGroup ng) {
+ AlgorithmParameters params = null;
+ if (ng.functions != null) {
+ params = ng.functions.getParameters();
}
-
- AlgorithmParameters params = namedGroupParams.get(namedGroup);
- try {
- return params.getParameterSpec(DHParameterSpec.class);
- } catch (InvalidParameterSpecException ipse) {
- // should be unlikely
- return getPredefinedDHParameterSpec(namedGroup);
- }
+ return params;
}
// Is there any supported group permitted by the constraints?
@@ -705,7 +897,7 @@
if (constraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
namedGroup.algorithm,
- namedGroupParams.get(namedGroup))) {
+ getParameters(namedGroup))) {
return true;
}
@@ -736,7 +928,7 @@
return constraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
namedGroup.algorithm,
- namedGroupParams.get(namedGroup));
+ getParameters(namedGroup));
}
// Is there any supported group permitted by the constraints?
@@ -760,7 +952,7 @@
constraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
namedGroup.algorithm,
- namedGroupParams.get(namedGroup))) {
+ getParameters(namedGroup))) {
return namedGroup;
}
}
@@ -777,7 +969,7 @@
constraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
namedGroup.algorithm,
- namedGroupParams.get(namedGroup))) {
+ getParameters(namedGroup))) {
return namedGroup;
}
}
@@ -825,7 +1017,7 @@
ng.isSupported(chc.activeCipherSuites) &&
chc.algorithmConstraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- ng.algorithm, namedGroupParams.get(ng))) {
+ ng.algorithm, getParameters(ng))) {
namedGroups.add(ng);
} else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
@@ -953,7 +1145,7 @@
ng.isSupported(shc.activeCipherSuites) &&
shc.algorithmConstraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- ng.algorithm, namedGroupParams.get(ng))) {
+ ng.algorithm, getParameters(ng))) {
namedGroups.add(ng);
} else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/XDHKeyExchange.java Thu Aug 30 11:08:01 2018 -0400
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2018, 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.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.interfaces.XECPublicKey;
+import java.security.spec.*;
+import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
+import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
+import sun.security.util.ECUtil;
+
+final class XDHKeyExchange {
+ static final SSLKeyAgreementGenerator xdheKAGenerator =
+ new XDHEKAGenerator();
+
+ static final class XDHECredentials implements SSLKeyAgreementCredentials {
+ final XECPublicKey popPublicKey;
+ final NamedGroup namedGroup;
+
+ XDHECredentials(XECPublicKey popPublicKey, NamedGroup namedGroup) {
+ this.popPublicKey = popPublicKey;
+ this.namedGroup = namedGroup;
+ }
+
+ @Override
+ public PublicKey getPublicKey() {
+ return popPublicKey;
+ }
+
+ static XDHECredentials valueOf(NamedGroup namedGroup,
+ byte[] encodedPoint) throws IOException, GeneralSecurityException {
+
+ if (namedGroup.type != NamedGroupType.NAMED_GROUP_XDH) {
+ throw new RuntimeException(
+ "Credentials decoding: Not XDH named group");
+ }
+
+ if (encodedPoint == null || encodedPoint.length == 0) {
+ return null;
+ }
+
+ NamedParameterSpec namedSpec =
+ new NamedParameterSpec(namedGroup.algorithm);
+ XECPublicKeySpec xecKeySpec =
+ ECUtil.decodeXecPublicKey(encodedPoint, namedSpec);
+ KeyFactory factory = JsseJce.getKeyFactory(namedGroup.algorithm);
+
+ XECPublicKey publicKey =
+ (XECPublicKey) factory.generatePublic(xecKeySpec);
+ return new XDHECredentials(publicKey, namedGroup);
+ }
+ }
+
+ static final class XDHEPossession implements SSLPossession {
+ final PrivateKey privateKey;
+ final XECPublicKey publicKey;
+ final NamedGroup namedGroup;
+
+ XDHEPossession(NamedGroup namedGroup, SecureRandom random) {
+ try {
+ KeyPairGenerator kpg =
+ JsseJce.getKeyPairGenerator(namedGroup.algorithm);
+ AlgorithmParameterSpec params = namedGroup.getParameterSpec();
+ kpg.initialize(params, random);
+ KeyPair kp = kpg.generateKeyPair();
+ privateKey = kp.getPrivate();
+ publicKey = (XECPublicKey) kp.getPublic();
+ } catch (GeneralSecurityException e) {
+ throw new RuntimeException(
+ "Could not generate XDH keypair", e);
+ }
+
+ this.namedGroup = namedGroup;
+ }
+
+ @Override
+ public byte[] encode() {
+ try {
+ return ECUtil.encodeXecPublicKey(publicKey.getU(),
+ publicKey.getParams());
+ } catch (InvalidParameterSpecException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+
+ private static final
+ class XDHEKAGenerator implements SSLKeyAgreementGenerator {
+ // Prevent instantiation of this class.
+ private XDHEKAGenerator() {
+ // blank
+ }
+
+ @Override
+ public SSLKeyDerivation createKeyDerivation(
+ HandshakeContext context) throws IOException {
+ XDHEPossession xdhePossession = null;
+ XDHECredentials xdheCredentials = null;
+ for (SSLPossession poss : context.handshakePossessions) {
+ if (!(poss instanceof XDHEPossession)) {
+ continue;
+ }
+
+ NamedGroup ng = ((XDHEPossession) poss).namedGroup;
+ for (SSLCredentials cred : context.handshakeCredentials) {
+ if (!(cred instanceof XDHECredentials)) {
+ continue;
+ }
+ if (ng.equals(((XDHECredentials) cred).namedGroup)) {
+ xdheCredentials = (XDHECredentials) cred;
+ break;
+ }
+ }
+
+ if (xdheCredentials != null) {
+ xdhePossession = (XDHEPossession) poss;
+ break;
+ }
+ }
+
+ if (xdhePossession == null || xdheCredentials == null) {
+ context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
+ "No sufficient XDHE key agreement parameters negotiated");
+ }
+
+ return new KAKeyDerivation("XDH", context,
+ xdhePossession.privateKey, xdheCredentials.popPublicKey);
+ }
+ }
+
+}
--- a/src/java.base/share/classes/sun/security/util/ArrayUtil.java Thu Aug 30 09:08:23 2018 -0400
+++ b/src/java.base/share/classes/sun/security/util/ArrayUtil.java Thu Aug 30 11:08:01 2018 -0400
@@ -32,7 +32,7 @@
/**
- * This class holds the various utility methods for array range checks.
+ * This class holds the various utility methods for arrays.
*/
public final class ArrayUtil {
@@ -52,4 +52,22 @@
// NPE is thrown when array is null
Preconditions.checkFromIndexSize(offset, len, array.length, AIOOBE_SUPPLIER);
}
+
+
+ private static void swap(byte[] arr, int i, int j) {
+ byte tmp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = tmp;
+ }
+
+ public static void reverse(byte [] arr) {
+ int i = 0;
+ int j = arr.length - 1;
+
+ while (i < j) {
+ swap(arr, i, j);
+ i++;
+ j--;
+ }
+ }
}
--- a/src/java.base/share/classes/sun/security/util/ECUtil.java Thu Aug 30 09:08:23 2018 -0400
+++ b/src/java.base/share/classes/sun/security/util/ECUtil.java Thu Aug 30 11:08:01 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, 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
@@ -227,5 +227,49 @@
return nameSpec.getName();
}
+ public static BigInteger decodeXecPublicKey(byte[] key,
+ XECParameters params) {
+
+ ArrayUtil.reverse(key);
+
+ // clear the extra bits
+ int bitsMod8 = params.getBits() % 8;
+ if (bitsMod8 != 0) {
+ int mask = (1 << bitsMod8) - 1;
+ key[0] &= mask;
+ }
+
+ return new BigInteger(1, key);
+ }
+
+ public static
+ XECPublicKeySpec decodeXecPublicKey(byte[] key,
+ AlgorithmParameterSpec spec)
+ throws InvalidParameterSpecException {
+
+ XECParameters params = XECParameters.get(
+ InvalidParameterSpecException::new, spec);
+ BigInteger u = decodeXecPublicKey(key, params);
+ return new XECPublicKeySpec(spec, u);
+ }
+
+ public static byte[] encodeXecPublicKey(BigInteger u,
+ XECParameters params) {
+
+ byte[] u_arr = u.toByteArray();
+ ArrayUtil.reverse(u_arr);
+ // u_arr may be too large or too small, depending on the value of u
+ return Arrays.copyOf(u_arr, params.getBytes());
+ }
+
+ public static byte[] encodeXecPublicKey(BigInteger u,
+ AlgorithmParameterSpec spec)
+ throws InvalidParameterSpecException {
+
+ XECParameters params = XECParameters.get(
+ InvalidParameterSpecException::new, spec);
+ return encodeXecPublicKey(u, params);
+ }
+
private ECUtil() {}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/util/XECParameters.java Thu Aug 30 11:08:01 2018 -0400
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2018, 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.util;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.NamedParameterSpec;
+import java.util.Collections;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import sun.security.util.ObjectIdentifier;
+import sun.security.x509.AlgorithmId;
+
+public class XECParameters {
+
+ // Naming/identification parameters
+ private final ObjectIdentifier oid;
+ private final String name;
+
+ // Curve/field parameters
+ private final int bits;
+ private final BigInteger p;
+ private final int logCofactor;
+ private final int a24;
+ private final byte basePoint;
+
+ /**
+ *
+ * Construct an object holding the supplied parameters. No parameters are
+ * checked, so this method always succeeds. This method supports
+ * Montgomery curves of the form y^2 = x^3 + ax^2 + x.
+ *
+ * @param bits The number of relevant bits in a public/private key.
+ * @param p The prime that defines the finite field.
+ * @param a24 The value of (a - 2) / 4, where a is the second-degree curve
+ * coefficient.
+ * @param basePoint The point that generates the desired group
+ * @param logCofactor The base-2 logarithm of the cofactor of the curve
+ * @param oid
+ * @param name
+ */
+ public XECParameters(int bits, BigInteger p, int a24,
+ byte basePoint, int logCofactor,
+ ObjectIdentifier oid, String name) {
+
+ this.bits = bits;
+ this.logCofactor = logCofactor;
+ this.p = p;
+ this.a24 = a24;
+ this.basePoint = basePoint;
+ this.oid = oid;
+ this.name = name;
+
+ }
+
+ public int getBits() {
+ return bits;
+ }
+ public int getBytes() {
+ return (bits + 7) / 8;
+ }
+ public int getLogCofactor() {
+ return logCofactor;
+ }
+ public BigInteger getP() {
+ return p;
+ }
+ public int getA24() {
+ return a24;
+ }
+ public byte getBasePoint() {
+ return basePoint;
+ }
+ public ObjectIdentifier getOid() {
+ return oid;
+ }
+ public String getName() {
+ return name;
+ }
+
+ private static final Map<Integer, XECParameters> SIZE_MAP;
+ private static final Map<ObjectIdentifier, XECParameters> OID_MAP;
+ private static final Map<String, XECParameters> NAME_MAP;
+
+ static {
+ final BigInteger TWO = BigInteger.valueOf(2);
+
+ Map<Integer, XECParameters> bySize = new HashMap<>();
+ Map<ObjectIdentifier, XECParameters> byOid = new HashMap<>();
+ Map<String, XECParameters> byName = new HashMap<>();
+
+ // set up X25519
+ try {
+ BigInteger p = TWO.pow(255).subtract(BigInteger.valueOf(19));
+ addParameters(255, p, 121665, (byte) 0x09, 3,
+ new int[]{1, 3, 101, 110}, NamedParameterSpec.X25519.getName(),
+ bySize, byOid, byName);
+
+ } catch (IOException ex) {
+ // Unable to set X25519 parameters---it will be disabled
+ }
+
+ // set up X448
+ try {
+ BigInteger p = TWO.pow(448).subtract(TWO.pow(224))
+ .subtract(BigInteger.ONE);
+ addParameters(448, p, 39081, (byte) 0x05, 2,
+ new int[]{1, 3, 101, 111}, NamedParameterSpec.X448.getName(),
+ bySize, byOid, byName);
+
+ } catch (IOException ex) {
+ // Unable to set X448 parameters---it will be disabled
+ }
+
+ SIZE_MAP = Collections.unmodifiableMap(bySize);
+ OID_MAP = Collections.unmodifiableMap(byOid);
+ NAME_MAP = Collections.unmodifiableMap(byName);
+ }
+
+ private static void addParameters(int bits, BigInteger p, int a24,
+ byte basePoint, int logCofactor, int[] oidBytes, String name,
+ Map<Integer, XECParameters> bySize,
+ Map<ObjectIdentifier, XECParameters> byOid,
+ Map<String, XECParameters> byName) throws IOException {
+
+ ObjectIdentifier oid = new ObjectIdentifier(oidBytes);
+ XECParameters params =
+ new XECParameters(bits, p, a24, basePoint, logCofactor, oid, name);
+ bySize.put(bits, params);
+ byOid.put(oid, params);
+ byName.put(name.toLowerCase(), params);
+ }
+
+ public static Optional<XECParameters> getByOid(ObjectIdentifier id) {
+ return Optional.ofNullable(OID_MAP.get(id));
+ }
+ public static Optional<XECParameters> getBySize(int size) {
+ return Optional.ofNullable(SIZE_MAP.get(size));
+ }
+ public static Optional<XECParameters> getByName(String name) {
+ return Optional.ofNullable(NAME_MAP.get(name.toLowerCase()));
+ }
+
+ public boolean oidEquals(XECParameters other) {
+ return oid.equals(other.getOid());
+ }
+
+ // Utility method that is used by the methods below to handle exception
+ // suppliers
+ private static
+ <A, B> Supplier<B> apply(final Function<A, B> func, final A a) {
+ return new Supplier<B>() {
+ @Override
+ public B get() {
+ return func.apply(a);
+ }
+ };
+ }
+
+ /**
+ * Get parameters by key size, or throw an exception if no parameters are
+ * defined for the specified key size. This method is used in several
+ * contexts that should throw different exceptions when the parameters
+ * are not found. The first argument is a function that produces the
+ * desired exception.
+ *
+ * @param exception a function that produces an exception from a string
+ * @param size the desired key size
+ * @param <T> the type of exception that is thrown
+ * @return the parameters for the specified key size
+ * @throws T when suitable parameters do not exist
+ */
+ public static
+ <T extends Throwable>
+ XECParameters getBySize(Function<String, T> exception,
+ int size) throws T {
+
+ Optional<XECParameters> xecParams = getBySize(size);
+ return xecParams.orElseThrow(
+ apply(exception, "Unsupported size: " + size));
+ }
+
+ /**
+ * Get parameters by algorithm ID, or throw an exception if no
+ * parameters are defined for the specified ID. This method is used in
+ * several contexts that should throw different exceptions when the
+ * parameters are not found. The first argument is a function that produces
+ * the desired exception.
+ *
+ * @param exception a function that produces an exception from a string
+ * @param algId the algorithm ID
+ * @param <T> the type of exception that is thrown
+ * @return the parameters for the specified algorithm ID
+ * @throws T when suitable parameters do not exist
+ */
+ public static
+ <T extends Throwable>
+ XECParameters get(Function<String, T> exception,
+ AlgorithmId algId) throws T {
+
+ Optional<XECParameters> xecParams = getByOid(algId.getOID());
+ return xecParams.orElseThrow(
+ apply(exception, "Unsupported OID: " + algId.getOID()));
+ }
+
+ /**
+ * Get parameters by algorithm parameter spec, or throw an exception if no
+ * parameters are defined for the spec. This method is used in
+ * several contexts that should throw different exceptions when the
+ * parameters are not found. The first argument is a function that produces
+ * the desired exception.
+ *
+ * @param exception a function that produces an exception from a string
+ * @param params the algorithm parameters spec
+ * @param <T> the type of exception that is thrown
+ * @return the parameters for the spec
+ * @throws T when suitable parameters do not exist
+ */
+ public static
+ <T extends Throwable>
+ XECParameters get(Function<String, T> exception,
+ AlgorithmParameterSpec params) throws T {
+
+ if (params instanceof NamedParameterSpec) {
+ NamedParameterSpec namedParams = (NamedParameterSpec) params;
+ Optional<XECParameters> xecParams =
+ getByName(namedParams.getName());
+ return xecParams.orElseThrow(
+ apply(exception, "Unsupported name: " + namedParams.getName()));
+ } else {
+ throw exception.apply("Only NamedParameterSpec is supported.");
+ }
+ }
+}
+
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyAgreement.java Thu Aug 30 09:08:23 2018 -0400
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyAgreement.java Thu Aug 30 11:08:01 2018 -0400
@@ -38,8 +38,11 @@
import javax.crypto.KeyAgreementSpi;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
+import javax.crypto.spec.SecretKeySpec;
import java.util.function.Function;
+import sun.security.util.XECParameters;
+
public class XDHKeyAgreement extends KeyAgreementSpi {
private byte[] privateKey;
@@ -202,7 +205,14 @@
throws IllegalStateException, NoSuchAlgorithmException,
InvalidKeyException {
- throw new NoSuchAlgorithmException("Not supported");
+ if (algorithm == null) {
+ throw new NoSuchAlgorithmException("Algorithm must not be null");
+ }
+ if (!(algorithm.equals("TlsPremasterSecret"))) {
+ throw new NoSuchAlgorithmException
+ ("Only supported for algorithm TlsPremasterSecret");
+ }
+ return new SecretKeySpec(engineGenerateSecret(), "TlsPremasterSecret");
}
static class X25519 extends XDHKeyAgreement {
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyFactory.java Thu Aug 30 09:08:23 2018 -0400
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyFactory.java Thu Aug 30 11:08:01 2018 -0400
@@ -44,6 +44,8 @@
import java.security.spec.XECPrivateKeySpec;
import java.util.function.Function;
+import sun.security.util.XECParameters;
+
public class XDHKeyFactory extends KeyFactorySpi {
private XECParameters lockedParams = null;
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyPairGenerator.java Thu Aug 30 09:08:23 2018 -0400
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyPairGenerator.java Thu Aug 30 11:08:01 2018 -0400
@@ -37,6 +37,7 @@
import java.security.spec.NamedParameterSpec;
import sun.security.jca.JCAUtil;
+import sun.security.util.XECParameters;
/**
* Key pair generator for the XDH key agreement algorithm.
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPrivateKeyImpl.java Thu Aug 30 09:08:23 2018 -0400
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPrivateKeyImpl.java Thu Aug 30 11:08:01 2018 -0400
@@ -28,11 +28,11 @@
import java.security.interfaces.XECPrivateKey;
import java.util.Optional;
import java.security.InvalidKeyException;
-import java.security.PrivateKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.NamedParameterSpec;
import sun.security.pkcs.PKCS8Key;
+import sun.security.util.XECParameters;
import sun.security.x509.AlgorithmId;
public final class XDHPrivateKeyImpl extends PKCS8Key implements XECPrivateKey {
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPublicKeyImpl.java Thu Aug 30 09:08:23 2018 -0400
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHPublicKeyImpl.java Thu Aug 30 11:08:01 2018 -0400
@@ -28,13 +28,13 @@
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyRep;
-import java.security.PublicKey;
import java.security.interfaces.XECPublicKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.NamedParameterSpec;
-import java.util.Arrays;
import sun.security.util.BitArray;
+import sun.security.util.ECUtil;
+import sun.security.util.XECParameters;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X509Key;
@@ -52,11 +52,7 @@
this.algid = new AlgorithmId(params.getOid());
this.u = u.mod(params.getP());
- byte[] u_arr = this.u.toByteArray();
- reverse(u_arr);
- // u_arr may be too large or too small, depending on the value of u
- u_arr = Arrays.copyOf(u_arr, params.getBytes());
-
+ byte[] u_arr = ECUtil.encodeXecPublicKey(this.u, params);
setKey(new BitArray(u_arr.length * 8, u_arr));
checkLength(params);
@@ -70,16 +66,7 @@
this.paramSpec = new NamedParameterSpec(params.getName());
// construct the BigInteger representation
byte[] u_arr = getKey().toByteArray();
- reverse(u_arr);
-
- // clear the extra bits
- int bitsMod8 = params.getBits() % 8;
- if (bitsMod8 != 0) {
- int mask = (1 << bitsMod8) - 1;
- u_arr[0] &= mask;
- }
-
- this.u = new BigInteger(1, u_arr);
+ this.u = ECUtil.decodeXecPublicKey(u_arr, params);
checkLength(params);
}
@@ -113,22 +100,5 @@
getFormat(),
getEncoded());
}
-
- private static void swap(byte[] arr, int i, int j) {
- byte tmp = arr[i];
- arr[i] = arr[j];
- arr[j] = tmp;
- }
-
- private static void reverse(byte [] arr) {
- int i = 0;
- int j = arr.length - 1;
-
- while (i < j) {
- swap(arr, i, j);
- i++;
- j--;
- }
- }
}
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/XECOperations.java Thu Aug 30 09:08:23 2018 -0400
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/XECOperations.java Thu Aug 30 11:08:01 2018 -0400
@@ -32,6 +32,7 @@
import sun.security.util.math.SmallValue;
import sun.security.util.math.intpoly.IntegerPolynomial25519;
import sun.security.util.math.intpoly.IntegerPolynomial448;
+import sun.security.util.XECParameters;
import java.math.BigInteger;
import java.security.ProviderException;
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/XECParameters.java Thu Aug 30 09:08:23 2018 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,263 +0,0 @@
-/*
- * Copyright (c) 2018, 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.ec;
-
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.NamedParameterSpec;
-import java.util.Collections;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Optional;
-import java.util.function.Function;
-import java.util.function.Supplier;
-
-import sun.security.util.ObjectIdentifier;
-import sun.security.x509.AlgorithmId;
-
-public class XECParameters {
-
- // Naming/identification parameters
- private final ObjectIdentifier oid;
- private final String name;
-
- // Curve/field parameters
- private final int bits;
- private final BigInteger p;
- private final int logCofactor;
- private final int a24;
- private final byte basePoint;
-
- /**
- *
- * Construct an object holding the supplied parameters. No parameters are
- * checked, so this method always succeeds. This method supports
- * Montgomery curves of the form y^2 = x^3 + ax^2 + x.
- *
- * @param bits The number of relevant bits in a public/private key.
- * @param p The prime that defines the finite field.
- * @param a24 The value of (a - 2) / 4, where a is the second-degree curve
- * coefficient.
- * @param basePoint The point that generates the desired group
- * @param logCofactor The base-2 logarithm of the cofactor of the curve
- * @param oid
- * @param name
- */
- public XECParameters(int bits, BigInteger p, int a24,
- byte basePoint, int logCofactor,
- ObjectIdentifier oid, String name) {
-
- this.bits = bits;
- this.logCofactor = logCofactor;
- this.p = p;
- this.a24 = a24;
- this.basePoint = basePoint;
- this.oid = oid;
- this.name = name;
-
- }
-
- public int getBits() {
- return bits;
- }
- public int getBytes() {
- return (bits + 7) / 8;
- }
- public int getLogCofactor() {
- return logCofactor;
- }
- public BigInteger getP() {
- return p;
- }
- public int getA24() {
- return a24;
- }
- public byte getBasePoint() {
- return basePoint;
- }
- public ObjectIdentifier getOid() {
- return oid;
- }
- public String getName() {
- return name;
- }
-
- private static final Map<Integer, XECParameters> SIZE_MAP;
- private static final Map<ObjectIdentifier, XECParameters> OID_MAP;
- private static final Map<String, XECParameters> NAME_MAP;
-
- static {
- final BigInteger TWO = BigInteger.valueOf(2);
-
- Map<Integer, XECParameters> bySize = new HashMap<>();
- Map<ObjectIdentifier, XECParameters> byOid = new HashMap<>();
- Map<String, XECParameters> byName = new HashMap<>();
-
- // set up X25519
- try {
- BigInteger p = TWO.pow(255).subtract(BigInteger.valueOf(19));
- addParameters(255, p, 121665, (byte) 0x09, 3,
- new int[]{1, 3, 101, 110}, NamedParameterSpec.X25519.getName(),
- bySize, byOid, byName);
-
- } catch (IOException ex) {
- // Unable to set X25519 parameters---it will be disabled
- }
-
- // set up X448
- try {
- BigInteger p = TWO.pow(448).subtract(TWO.pow(224))
- .subtract(BigInteger.ONE);
- addParameters(448, p, 39081, (byte) 0x05, 2,
- new int[]{1, 3, 101, 111}, NamedParameterSpec.X448.getName(),
- bySize, byOid, byName);
-
- } catch (IOException ex) {
- // Unable to set X448 parameters---it will be disabled
- }
-
- SIZE_MAP = Collections.unmodifiableMap(bySize);
- OID_MAP = Collections.unmodifiableMap(byOid);
- NAME_MAP = Collections.unmodifiableMap(byName);
- }
-
- private static void addParameters(int bits, BigInteger p, int a24,
- byte basePoint, int logCofactor, int[] oidBytes, String name,
- Map<Integer, XECParameters> bySize,
- Map<ObjectIdentifier, XECParameters> byOid,
- Map<String, XECParameters> byName) throws IOException {
-
- ObjectIdentifier oid = new ObjectIdentifier(oidBytes);
- XECParameters params =
- new XECParameters(bits, p, a24, basePoint, logCofactor, oid, name);
- bySize.put(bits, params);
- byOid.put(oid, params);
- byName.put(name, params);
- }
-
- public static Optional<XECParameters> getByOid(ObjectIdentifier id) {
- return Optional.ofNullable(OID_MAP.get(id));
- }
- public static Optional<XECParameters> getBySize(int size) {
- return Optional.ofNullable(SIZE_MAP.get(size));
- }
- public static Optional<XECParameters> getByName(String name) {
- return Optional.ofNullable(NAME_MAP.get(name));
- }
-
- boolean oidEquals(XECParameters other) {
- return oid.equals(other.getOid());
- }
-
- // Utility method that is used by the methods below to handle exception
- // suppliers
- private static
- <A, B> Supplier<B> apply(final Function<A, B> func, final A a) {
- return new Supplier<B>() {
- @Override
- public B get() {
- return func.apply(a);
- }
- };
- }
-
- /**
- * Get parameters by key size, or throw an exception if no parameters are
- * defined for the specified key size. This method is used in several
- * contexts that should throw different exceptions when the parameters
- * are not found. The first argument is a function that produces the
- * desired exception.
- *
- * @param exception a function that produces an exception from a string
- * @param size the desired key size
- * @param <T> the type of exception that is thrown
- * @return the parameters for the specified key size
- * @throws T when suitable parameters do not exist
- */
- public static
- <T extends Throwable>
- XECParameters getBySize(Function<String, T> exception,
- int size) throws T {
-
- Optional<XECParameters> xecParams = getBySize(size);
- return xecParams.orElseThrow(
- apply(exception, "Unsupported size: " + size));
- }
-
- /**
- * Get parameters by algorithm ID, or throw an exception if no
- * parameters are defined for the specified ID. This method is used in
- * several contexts that should throw different exceptions when the
- * parameters are not found. The first argument is a function that produces
- * the desired exception.
- *
- * @param exception a function that produces an exception from a string
- * @param algId the algorithm ID
- * @param <T> the type of exception that is thrown
- * @return the parameters for the specified algorithm ID
- * @throws T when suitable parameters do not exist
- */
- public static
- <T extends Throwable>
- XECParameters get(Function<String, T> exception,
- AlgorithmId algId) throws T {
-
- Optional<XECParameters> xecParams = getByOid(algId.getOID());
- return xecParams.orElseThrow(
- apply(exception, "Unsupported OID: " + algId.getOID()));
- }
-
- /**
- * Get parameters by algorithm parameter spec, or throw an exception if no
- * parameters are defined for the spec. This method is used in
- * several contexts that should throw different exceptions when the
- * parameters are not found. The first argument is a function that produces
- * the desired exception.
- *
- * @param exception a function that produces an exception from a string
- * @param params the algorithm parameters spec
- * @param <T> the type of exception that is thrown
- * @return the parameters for the spec
- * @throws T when suitable parameters do not exist
- */
- public static
- <T extends Throwable>
- XECParameters get(Function<String, T> exception,
- AlgorithmParameterSpec params) throws T {
-
- if (params instanceof NamedParameterSpec) {
- NamedParameterSpec namedParams = (NamedParameterSpec) params;
- Optional<XECParameters> xecParams =
- getByName(namedParams.getName());
- return xecParams.orElseThrow(
- apply(exception, "Unsupported name: " + namedParams.getName()));
- } else {
- throw exception.apply("Only NamedParameterSpec is supported.");
- }
- }
-}
-
--- a/test/jdk/sun/security/ec/xec/TestXECOps.java Thu Aug 30 09:08:23 2018 -0400
+++ b/test/jdk/sun/security/ec/xec/TestXECOps.java Thu Aug 30 11:08:01 2018 -0400
@@ -25,12 +25,13 @@
* @test
* @bug 8171277
* @summary Test XEC curve operations
- * @modules jdk.crypto.ec/sun.security.ec
+ * @modules java.base/sun.security.util jdk.crypto.ec/sun.security.ec
* @library /test/lib
* @build jdk.test.lib.Convert
* @run main TestXECOps
*/
+import sun.security.util.*;
import sun.security.ec.*;
import java.util.*;
import jdk.test.lib.Convert;
--- a/test/jdk/sun/security/ec/xec/XECIterative.java Thu Aug 30 09:08:23 2018 -0400
+++ b/test/jdk/sun/security/ec/xec/XECIterative.java Thu Aug 30 11:08:01 2018 -0400
@@ -27,7 +27,7 @@
* @summary XEC curve operations iterative test vectors
* @library /test/lib
* @build jdk.test.lib.Convert
- * @modules jdk.crypto.ec/sun.security.ec
+ * @modules java.base/sun.security.util jdk.crypto.ec/sun.security.ec
* @run main XECIterative 0 10000
* @run main XECIterative 10000 20000
* @run main XECIterative 20000 30000
@@ -40,6 +40,7 @@
* @run main XECIterative 90000 100000
*/
+import sun.security.util.*;
import sun.security.ec.*;
import java.io.*;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/CipherSuite/SupportedGroups.java Thu Aug 30 11:08:01 2018 -0400
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*
+ * @test
+ * @bug 8171279
+ * @library /javax/net/ssl/templates
+ * @summary Test TLS connection with each individual supported group
+ * @run main/othervm SupportedGroups secp256r1
+ * @run main/othervm SupportedGroups secp384r1
+ * @run main/othervm SupportedGroups secp521r1
+ * @run main/othervm SupportedGroups x25519
+ * @run main/othervm SupportedGroups x448
+ * @run main/othervm SupportedGroups ffdhe2048
+ * @run main/othervm SupportedGroups ffdhe3072
+ * @run main/othervm SupportedGroups ffdhe4096
+ * @run main/othervm SupportedGroups ffdhe6144
+ * @run main/othervm SupportedGroups ffdhe8192
+ */
+
+
+public class SupportedGroups extends SSLSocketTemplate {
+ /*
+ * Run the test case.
+ */
+ public static void main(String[] args) throws Exception {
+ System.setProperty("jdk.tls.namedGroups", args[0]);
+
+ (new SupportedGroups()).run();
+ }
+}