8140436: Negotiated Finite Field Diffie-Hellman Ephemeral Parameters for TLS
Reviewed-by: valeriep, jnimeh, apetcher
This commit is contained in:
parent
7a4f23e55d
commit
d9de25905c
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -44,6 +44,7 @@ import static sun.security.ssl.CipherSuite.CipherType.*;
|
|||||||
import static sun.security.ssl.CipherSuite.MacAlg.*;
|
import static sun.security.ssl.CipherSuite.MacAlg.*;
|
||||||
import static sun.security.ssl.CipherSuite.BulkCipher.*;
|
import static sun.security.ssl.CipherSuite.BulkCipher.*;
|
||||||
import static sun.security.ssl.JsseJce.*;
|
import static sun.security.ssl.JsseJce.*;
|
||||||
|
import static sun.security.ssl.NamedGroupType.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An SSL/TLS CipherSuite. Constants for the standard key exchange, cipher,
|
* An SSL/TLS CipherSuite. Constants for the standard key exchange, cipher,
|
||||||
@ -376,38 +377,38 @@ final class CipherSuite implements Comparable<CipherSuite> {
|
|||||||
static enum KeyExchange {
|
static enum KeyExchange {
|
||||||
|
|
||||||
// key exchange algorithms
|
// key exchange algorithms
|
||||||
K_NULL ("NULL", false, false),
|
K_NULL ("NULL", false, NAMED_GROUP_NONE),
|
||||||
K_RSA ("RSA", true, false),
|
K_RSA ("RSA", true, NAMED_GROUP_NONE),
|
||||||
K_RSA_EXPORT ("RSA_EXPORT", true, false),
|
K_RSA_EXPORT ("RSA_EXPORT", true, NAMED_GROUP_NONE),
|
||||||
K_DH_RSA ("DH_RSA", false, false),
|
K_DH_RSA ("DH_RSA", false, NAMED_GROUP_NONE),
|
||||||
K_DH_DSS ("DH_DSS", false, false),
|
K_DH_DSS ("DH_DSS", false, NAMED_GROUP_NONE),
|
||||||
K_DHE_DSS ("DHE_DSS", true, false),
|
K_DHE_DSS ("DHE_DSS", true, NAMED_GROUP_FFDHE),
|
||||||
K_DHE_RSA ("DHE_RSA", true, false),
|
K_DHE_RSA ("DHE_RSA", true, NAMED_GROUP_FFDHE),
|
||||||
K_DH_ANON ("DH_anon", true, false),
|
K_DH_ANON ("DH_anon", true, NAMED_GROUP_FFDHE),
|
||||||
|
|
||||||
K_ECDH_ECDSA ("ECDH_ECDSA", ALLOW_ECC, true),
|
K_ECDH_ECDSA ("ECDH_ECDSA", ALLOW_ECC, NAMED_GROUP_ECDHE),
|
||||||
K_ECDH_RSA ("ECDH_RSA", ALLOW_ECC, true),
|
K_ECDH_RSA ("ECDH_RSA", ALLOW_ECC, NAMED_GROUP_ECDHE),
|
||||||
K_ECDHE_ECDSA("ECDHE_ECDSA", ALLOW_ECC, true),
|
K_ECDHE_ECDSA("ECDHE_ECDSA", ALLOW_ECC, NAMED_GROUP_ECDHE),
|
||||||
K_ECDHE_RSA ("ECDHE_RSA", ALLOW_ECC, true),
|
K_ECDHE_RSA ("ECDHE_RSA", ALLOW_ECC, NAMED_GROUP_ECDHE),
|
||||||
K_ECDH_ANON ("ECDH_anon", ALLOW_ECC, true),
|
K_ECDH_ANON ("ECDH_anon", ALLOW_ECC, NAMED_GROUP_ECDHE),
|
||||||
|
|
||||||
// Kerberos cipher suites
|
// Kerberos cipher suites
|
||||||
K_KRB5 ("KRB5", true, false),
|
K_KRB5 ("KRB5", true, NAMED_GROUP_NONE),
|
||||||
K_KRB5_EXPORT("KRB5_EXPORT", true, false),
|
K_KRB5_EXPORT("KRB5_EXPORT", true, NAMED_GROUP_NONE),
|
||||||
|
|
||||||
// renegotiation protection request signaling cipher suite
|
// 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
|
// name of the key exchange algorithm, e.g. DHE_DSS
|
||||||
final String name;
|
final String name;
|
||||||
final boolean allowed;
|
final boolean allowed;
|
||||||
final boolean isEC;
|
final NamedGroupType groupType;
|
||||||
private final boolean alwaysAvailable;
|
private final boolean alwaysAvailable;
|
||||||
|
|
||||||
KeyExchange(String name, boolean allowed, boolean isEC) {
|
KeyExchange(String name, boolean allowed, NamedGroupType groupType) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.allowed = allowed;
|
this.allowed = allowed;
|
||||||
this.isEC = isEC;
|
this.groupType = groupType;
|
||||||
this.alwaysAvailable = allowed &&
|
this.alwaysAvailable = allowed &&
|
||||||
(!name.startsWith("EC")) && (!name.startsWith("KRB"));
|
(!name.startsWith("EC")) && (!name.startsWith("KRB"));
|
||||||
}
|
}
|
||||||
@ -417,7 +418,7 @@ final class CipherSuite implements Comparable<CipherSuite> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isEC) {
|
if (groupType == NAMED_GROUP_ECDHE) {
|
||||||
return (allowed && JsseJce.isEcAvailable());
|
return (allowed && JsseJce.isEcAvailable());
|
||||||
} else if (name.startsWith("KRB")) {
|
} else if (name.startsWith("KRB")) {
|
||||||
return (allowed && JsseJce.isKerberosAvailable());
|
return (allowed && JsseJce.isKerberosAvailable());
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -30,6 +30,7 @@ import java.io.*;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import javax.net.ssl.SSLException;
|
import javax.net.ssl.SSLException;
|
||||||
|
import static sun.security.ssl.NamedGroupType.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of CipherSuites. Also maintains the lists of supported and
|
* A list of CipherSuites. Also maintains the lists of supported and
|
||||||
@ -42,15 +43,16 @@ final class CipherSuiteList {
|
|||||||
|
|
||||||
private final Collection<CipherSuite> cipherSuites;
|
private final Collection<CipherSuite> cipherSuites;
|
||||||
private String[] suiteNames;
|
private String[] suiteNames;
|
||||||
|
private final EnumSet<NamedGroupType> groupsTypes =
|
||||||
// flag indicating whether this list contains any ECC ciphersuites.
|
EnumSet.noneOf(NamedGroupType.class);
|
||||||
// null if not yet checked.
|
|
||||||
private volatile Boolean containsEC;
|
|
||||||
|
|
||||||
// for use by buildAvailableCache() and
|
// for use by buildAvailableCache() and
|
||||||
// Handshaker.getKickstartMessage() only
|
// Handshaker.getKickstartMessage() only
|
||||||
CipherSuiteList(Collection<CipherSuite> cipherSuites) {
|
CipherSuiteList(Collection<CipherSuite> cipherSuites) {
|
||||||
this.cipherSuites = cipherSuites;
|
this.cipherSuites = cipherSuites;
|
||||||
|
for (CipherSuite suite : cipherSuites) {
|
||||||
|
updateGroupTypes(suite);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,6 +61,7 @@ final class CipherSuiteList {
|
|||||||
CipherSuiteList(CipherSuite suite) {
|
CipherSuiteList(CipherSuite suite) {
|
||||||
cipherSuites = new ArrayList<CipherSuite>(1);
|
cipherSuites = new ArrayList<CipherSuite>(1);
|
||||||
cipherSuites.add(suite);
|
cipherSuites.add(suite);
|
||||||
|
updateGroupTypes(suite);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,6 +85,7 @@ final class CipherSuiteList {
|
|||||||
+ suiteName + " with currently installed providers");
|
+ suiteName + " with currently installed providers");
|
||||||
}
|
}
|
||||||
cipherSuites.add(suite);
|
cipherSuites.add(suite);
|
||||||
|
updateGroupTypes(suite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +101,20 @@ final class CipherSuiteList {
|
|||||||
}
|
}
|
||||||
cipherSuites = new ArrayList<CipherSuite>(bytes.length >> 1);
|
cipherSuites = new ArrayList<CipherSuite>(bytes.length >> 1);
|
||||||
for (int i = 0; i < bytes.length; i += 2) {
|
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 @@ final class CipherSuiteList {
|
|||||||
return cipherSuites.contains(suite);
|
return cipherSuites.contains(suite);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return whether this list contains any ECC ciphersuites
|
// Return whether this list contains cipher suites of a named group type.
|
||||||
boolean containsEC() {
|
boolean contains(NamedGroupType groupType) {
|
||||||
if (containsEC == null) {
|
return groupsTypes.contains(groupType);
|
||||||
for (CipherSuite c : cipherSuites) {
|
|
||||||
if (c.keyExchange.isEC) {
|
|
||||||
containsEC = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
containsEC = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return containsEC;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -148,6 +148,10 @@ final class ClientHandshaker extends Handshaker {
|
|||||||
private static final boolean enableMFLExtension =
|
private static final boolean enableMFLExtension =
|
||||||
Debug.getBooleanProperty("jsse.enableMFLExtension", false);
|
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
|
// Whether an ALPN extension was sent in the ClientHello
|
||||||
private boolean alpnActive = false;
|
private boolean alpnActive = false;
|
||||||
|
|
||||||
@ -767,13 +771,15 @@ final class ClientHandshaker extends Handshaker {
|
|||||||
fatalSE(Alerts.alert_unexpected_message, "Server set " +
|
fatalSE(Alerts.alert_unexpected_message, "Server set " +
|
||||||
type + " extension when not requested by client");
|
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_EC_POINT_FORMATS)
|
||||||
&& (type != ExtensionType.EXT_SERVER_NAME)
|
&& (type != ExtensionType.EXT_SERVER_NAME)
|
||||||
&& (type != ExtensionType.EXT_ALPN)
|
&& (type != ExtensionType.EXT_ALPN)
|
||||||
&& (type != ExtensionType.EXT_RENEGOTIATION_INFO)
|
&& (type != ExtensionType.EXT_RENEGOTIATION_INFO)
|
||||||
&& (type != ExtensionType.EXT_STATUS_REQUEST)
|
&& (type != ExtensionType.EXT_STATUS_REQUEST)
|
||||||
&& (type != ExtensionType.EXT_STATUS_REQUEST_V2)) {
|
&& (type != ExtensionType.EXT_STATUS_REQUEST_V2)) {
|
||||||
|
// Note: Better to check client requested extensions rather
|
||||||
|
// than all supported extensions.
|
||||||
fatalSE(Alerts.alert_unsupported_extension,
|
fatalSE(Alerts.alert_unsupported_extension,
|
||||||
"Server sent an unsupported extension: " + type);
|
"Server sent an unsupported extension: " + type);
|
||||||
}
|
}
|
||||||
@ -823,6 +829,17 @@ final class ClientHandshaker extends Handshaker {
|
|||||||
* our own D-H algorithm object so we can defer key calculations
|
* our own D-H algorithm object so we can defer key calculations
|
||||||
* until after we've sent the client key exchange message (which
|
* until after we've sent the client key exchange message (which
|
||||||
* gives client and server some useful parallelism).
|
* 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)
|
private void serverKeyExchange(DH_ServerKeyExchange mesg)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
@ -1495,14 +1512,17 @@ final class ClientHandshaker extends Handshaker {
|
|||||||
sslContext.getSecureRandom(), maxProtocolVersion,
|
sslContext.getSecureRandom(), maxProtocolVersion,
|
||||||
sessionId, cipherSuites, isDTLS);
|
sessionId, cipherSuites, isDTLS);
|
||||||
|
|
||||||
// add elliptic curves and point format extensions
|
// Add named groups extension for ECDHE and FFDHE if necessary.
|
||||||
if (cipherSuites.containsEC()) {
|
SupportedGroupsExtension sge =
|
||||||
EllipticCurvesExtension ece =
|
SupportedGroupsExtension.createExtension(
|
||||||
EllipticCurvesExtension.createExtension(algorithmConstraints);
|
algorithmConstraints,
|
||||||
if (ece != null) {
|
cipherSuites, enableFFDHE);
|
||||||
clientHelloMessage.extensions.add(ece);
|
if (sge != null) {
|
||||||
|
clientHelloMessage.extensions.add(sge);
|
||||||
|
// Add elliptic point format extensions
|
||||||
|
if (cipherSuites.contains(NamedGroupType.NAMED_GROUP_ECDHE)) {
|
||||||
clientHelloMessage.extensions.add(
|
clientHelloMessage.extensions.add(
|
||||||
EllipticPointFormatsExtension.DEFAULT);
|
EllipticPointFormatsExtension.DEFAULT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -26,14 +26,8 @@
|
|||||||
|
|
||||||
package sun.security.ssl;
|
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.math.BigInteger;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.io.IOException;
|
|
||||||
import javax.net.ssl.SSLHandshakeException;
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import javax.crypto.KeyAgreement;
|
import javax.crypto.KeyAgreement;
|
||||||
@ -101,7 +95,7 @@ final class DHCrypt {
|
|||||||
*/
|
*/
|
||||||
DHCrypt(int keyLength, SecureRandom random) {
|
DHCrypt(int keyLength, SecureRandom random) {
|
||||||
this(keyLength,
|
this(keyLength,
|
||||||
ParametersHolder.definedParams.get(keyLength), random);
|
PredefinedDHParameterSpecs.definedParams.get(keyLength), random);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -115,6 +109,14 @@ final class DHCrypt {
|
|||||||
new DHParameterSpec(modulus, base), random);
|
new DHParameterSpec(modulus, base), random);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* Generate a Diffie-Hellman keypair using the specified size and
|
||||||
* parameters.
|
* parameters.
|
||||||
@ -272,266 +274,5 @@ final class DHCrypt {
|
|||||||
|
|
||||||
return null;
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -56,17 +56,17 @@ final class ECDHCrypt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called by ServerHandshaker for ephemeral ECDH
|
// Called by ServerHandshaker for ephemeral ECDH
|
||||||
ECDHCrypt(int curveId, SecureRandom random) {
|
ECDHCrypt(NamedGroup namedGroup, SecureRandom random) {
|
||||||
try {
|
try {
|
||||||
KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
|
KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
|
||||||
ECGenParameterSpec params =
|
ECGenParameterSpec params =
|
||||||
EllipticCurvesExtension.getECGenParamSpec(curveId);
|
SupportedGroupsExtension.getECGenParamSpec(namedGroup);
|
||||||
kpg.initialize(params, random);
|
kpg.initialize(params, random);
|
||||||
KeyPair kp = kpg.generateKeyPair();
|
KeyPair kp = kpg.generateKeyPair();
|
||||||
privateKey = kp.getPrivate();
|
privateKey = kp.getPrivate();
|
||||||
publicKey = (ECPublicKey)kp.getPublic();
|
publicKey = (ECPublicKey)kp.getPublic();
|
||||||
} catch (GeneralSecurityException e) {
|
} 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 @@ final class ECDHCrypt {
|
|||||||
privateKey = kp.getPrivate();
|
privateKey = kp.getPrivate();
|
||||||
publicKey = (ECPublicKey)kp.getPublic();
|
publicKey = (ECPublicKey)kp.getPublic();
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
throw new RuntimeException("Could not generate DH keypair", e);
|
throw new RuntimeException("Could not generate ECDH keypair", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -82,9 +82,9 @@ final class ExtensionType {
|
|||||||
static final ExtensionType EXT_CERT_TYPE =
|
static final ExtensionType EXT_CERT_TYPE =
|
||||||
e(0x0009, "cert_type"); // IANA registry value: 9
|
e(0x0009, "cert_type"); // IANA registry value: 9
|
||||||
|
|
||||||
// extensions defined in RFC 4492 (ECC)
|
// extensions defined in RFC 4492 (ECC) and RFC 7919 (FFDHE)
|
||||||
static final ExtensionType EXT_ELLIPTIC_CURVES =
|
static final ExtensionType EXT_SUPPORTED_GROUPS =
|
||||||
e(0x000A, "elliptic_curves"); // IANA registry value: 10
|
e(0x000A, "supported_groups"); // IANA registry value: 10
|
||||||
static final ExtensionType EXT_EC_POINT_FORMATS =
|
static final ExtensionType EXT_EC_POINT_FORMATS =
|
||||||
e(0x000B, "ec_point_formats"); // IANA registry value: 11
|
e(0x000B, "ec_point_formats"); // IANA registry value: 11
|
||||||
|
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -1369,8 +1369,9 @@ class ECDH_ServerKeyExchange extends ServerKeyExchange {
|
|||||||
private static final int CURVE_EXPLICIT_CHAR2 = 2;
|
private static final int CURVE_EXPLICIT_CHAR2 = 2;
|
||||||
private static final int CURVE_NAMED_CURVE = 3;
|
private static final int CURVE_NAMED_CURVE = 3;
|
||||||
|
|
||||||
// id of the curve we are using
|
// id of the named group we are using
|
||||||
private int curveId;
|
private int groupId;
|
||||||
|
|
||||||
// encoded public point
|
// encoded public point
|
||||||
private byte[] pointBytes;
|
private byte[] pointBytes;
|
||||||
|
|
||||||
@ -1389,7 +1390,8 @@ class ECDH_ServerKeyExchange extends ServerKeyExchange {
|
|||||||
ECDH_ServerKeyExchange(ECDHCrypt obj, PrivateKey privateKey,
|
ECDH_ServerKeyExchange(ECDHCrypt obj, PrivateKey privateKey,
|
||||||
byte[] clntNonce, byte[] svrNonce, SecureRandom sr,
|
byte[] clntNonce, byte[] svrNonce, SecureRandom sr,
|
||||||
SignatureAndHashAlgorithm signAlgorithm,
|
SignatureAndHashAlgorithm signAlgorithm,
|
||||||
ProtocolVersion protocolVersion) throws GeneralSecurityException {
|
ProtocolVersion protocolVersion)
|
||||||
|
throws SSLHandshakeException, GeneralSecurityException {
|
||||||
|
|
||||||
this.protocolVersion = protocolVersion;
|
this.protocolVersion = protocolVersion;
|
||||||
|
|
||||||
@ -1397,7 +1399,14 @@ class ECDH_ServerKeyExchange extends ServerKeyExchange {
|
|||||||
ECParameterSpec params = publicKey.getParams();
|
ECParameterSpec params = publicKey.getParams();
|
||||||
ECPoint point = publicKey.getW();
|
ECPoint point = publicKey.getW();
|
||||||
pointBytes = JsseJce.encodePoint(point, params.getCurve());
|
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) {
|
if (privateKey == null) {
|
||||||
// ECDH_anon
|
// ECDH_anon
|
||||||
@ -1434,20 +1443,27 @@ class ECDH_ServerKeyExchange extends ServerKeyExchange {
|
|||||||
// These parsing errors should never occur as we negotiated
|
// These parsing errors should never occur as we negotiated
|
||||||
// the supported curves during the exchange of the Hello messages.
|
// the supported curves during the exchange of the Hello messages.
|
||||||
if (curveType == CURVE_NAMED_CURVE) {
|
if (curveType == CURVE_NAMED_CURVE) {
|
||||||
curveId = input.getInt16();
|
groupId = input.getInt16();
|
||||||
if (!EllipticCurvesExtension.isSupported(curveId)) {
|
NamedGroup namedGroup = NamedGroup.valueOf(groupId);
|
||||||
|
if (namedGroup == null) {
|
||||||
throw new SSLHandshakeException(
|
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(
|
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) {
|
if (parameters == null) {
|
||||||
throw new SSLHandshakeException(
|
throw new SSLHandshakeException(
|
||||||
"Unsupported curve: " + curveOid);
|
"No supported EC parameter for named group: " + namedGroup);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new SSLHandshakeException(
|
throw new SSLHandshakeException(
|
||||||
@ -1530,8 +1546,8 @@ class ECDH_ServerKeyExchange extends ServerKeyExchange {
|
|||||||
sig.update(svrNonce);
|
sig.update(svrNonce);
|
||||||
|
|
||||||
sig.update((byte)CURVE_NAMED_CURVE);
|
sig.update((byte)CURVE_NAMED_CURVE);
|
||||||
sig.update((byte)(curveId >> 8));
|
sig.update((byte)(groupId >> 8));
|
||||||
sig.update((byte)curveId);
|
sig.update((byte)groupId);
|
||||||
sig.update((byte)pointBytes.length);
|
sig.update((byte)pointBytes.length);
|
||||||
sig.update(pointBytes);
|
sig.update(pointBytes);
|
||||||
}
|
}
|
||||||
@ -1552,7 +1568,7 @@ class ECDH_ServerKeyExchange extends ServerKeyExchange {
|
|||||||
@Override
|
@Override
|
||||||
void send(HandshakeOutStream s) throws IOException {
|
void send(HandshakeOutStream s) throws IOException {
|
||||||
s.putInt8(CURVE_NAMED_CURVE);
|
s.putInt8(CURVE_NAMED_CURVE);
|
||||||
s.putInt16(curveId);
|
s.putInt16(groupId);
|
||||||
s.putBytes8(pointBytes);
|
s.putBytes8(pointBytes);
|
||||||
|
|
||||||
if (signatureBytes != null) {
|
if (signatureBytes != null) {
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -52,6 +52,7 @@ import sun.security.ssl.CipherSuite.*;
|
|||||||
|
|
||||||
import static sun.security.ssl.CipherSuite.PRF.*;
|
import static sun.security.ssl.CipherSuite.PRF.*;
|
||||||
import static sun.security.ssl.CipherSuite.CipherType.*;
|
import static sun.security.ssl.CipherSuite.CipherType.*;
|
||||||
|
import static sun.security.ssl.NamedGroupType.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handshaker ... processes handshake records from an SSL V3.0
|
* Handshaker ... processes handshake records from an SSL V3.0
|
||||||
@ -685,42 +686,14 @@ abstract class Handshaker {
|
|||||||
ArrayList<CipherSuite> suites = new ArrayList<>();
|
ArrayList<CipherSuite> suites = new ArrayList<>();
|
||||||
if (!(activeProtocols.collection().isEmpty()) &&
|
if (!(activeProtocols.collection().isEmpty()) &&
|
||||||
activeProtocols.min.v != ProtocolVersion.NONE.v) {
|
activeProtocols.min.v != ProtocolVersion.NONE.v) {
|
||||||
boolean checkedCurves = false;
|
Map<NamedGroupType, Boolean> cachedStatus =
|
||||||
boolean hasCurves = false;
|
new EnumMap<>(NamedGroupType.class);
|
||||||
for (CipherSuite suite : enabledCipherSuites.collection()) {
|
for (CipherSuite suite : enabledCipherSuites.collection()) {
|
||||||
if (!activeProtocols.min.obsoletes(suite) &&
|
if (suite.isAvailable() &&
|
||||||
|
(!activeProtocols.min.obsoletes(suite)) &&
|
||||||
activeProtocols.max.supports(suite)) {
|
activeProtocols.max.supports(suite)) {
|
||||||
if (algorithmConstraints.permits(
|
if (isActivatable(suite, cachedStatus)) {
|
||||||
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
|
suites.add(suite);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (debug != null && Debug.isOn("verbose")) {
|
} else if (debug != null && Debug.isOn("verbose")) {
|
||||||
if (activeProtocols.min.obsoletes(suite)) {
|
if (activeProtocols.min.obsoletes(suite)) {
|
||||||
@ -779,46 +752,15 @@ abstract class Handshaker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
|
Map<NamedGroupType, Boolean> cachedStatus =
|
||||||
|
new EnumMap<>(NamedGroupType.class);
|
||||||
for (CipherSuite suite : enabledCipherSuites.collection()) {
|
for (CipherSuite suite : enabledCipherSuites.collection()) {
|
||||||
if (suite.isAvailable() && (!protocol.obsoletes(suite)) &&
|
if (suite.isAvailable() && (!protocol.obsoletes(suite)) &&
|
||||||
protocol.supports(suite)) {
|
protocol.supports(suite)) {
|
||||||
if (algorithmConstraints.permits(
|
if (isActivatable(suite, cachedStatus)) {
|
||||||
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
|
protocols.add(protocol);
|
||||||
suite.name, null)) {
|
found = true;
|
||||||
|
break;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
} else if (debug != null && Debug.isOn("verbose")) {
|
} else if (debug != null && Debug.isOn("verbose")) {
|
||||||
System.out.println(
|
System.out.println(
|
||||||
@ -826,6 +768,7 @@ abstract class Handshaker {
|
|||||||
" for " + protocol);
|
" for " + protocol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found && (debug != null) && Debug.isOn("handshake")) {
|
if (!found && (debug != null) && Debug.isOn("handshake")) {
|
||||||
System.out.println(
|
System.out.println(
|
||||||
"No available cipher suite for " + protocol);
|
"No available cipher suite for " + protocol);
|
||||||
@ -842,6 +785,43 @@ abstract class Handshaker {
|
|||||||
return activeProtocols;
|
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
|
* As long as handshaking has not activated, we can
|
||||||
* change whether session creations are allowed.
|
* change whether session creations are allowed.
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -49,7 +49,7 @@ import javax.net.ssl.*;
|
|||||||
* explicitly support.
|
* explicitly support.
|
||||||
* . ServerNameExtension: the server_name extension.
|
* . ServerNameExtension: the server_name extension.
|
||||||
* . SignatureAlgorithmsExtension: the signature_algorithms extension.
|
* . SignatureAlgorithmsExtension: the signature_algorithms extension.
|
||||||
* . EllipticCurvesExtension: the ECC supported curves extension.
|
* . SupportedGroupsExtension: the supported groups extension.
|
||||||
* . EllipticPointFormatsExtension: the ECC supported point formats
|
* . EllipticPointFormatsExtension: the ECC supported point formats
|
||||||
* (compressed/uncompressed) extension.
|
* (compressed/uncompressed) extension.
|
||||||
* . ALPNExtension: the application_layer_protocol_negotiation extension.
|
* . ALPNExtension: the application_layer_protocol_negotiation extension.
|
||||||
@ -79,8 +79,8 @@ final class HelloExtensions {
|
|||||||
extension = new ServerNameExtension(s, extlen);
|
extension = new ServerNameExtension(s, extlen);
|
||||||
} else if (extType == ExtensionType.EXT_SIGNATURE_ALGORITHMS) {
|
} else if (extType == ExtensionType.EXT_SIGNATURE_ALGORITHMS) {
|
||||||
extension = new SignatureAlgorithmsExtension(s, extlen);
|
extension = new SignatureAlgorithmsExtension(s, extlen);
|
||||||
} else if (extType == ExtensionType.EXT_ELLIPTIC_CURVES) {
|
} else if (extType == ExtensionType.EXT_SUPPORTED_GROUPS) {
|
||||||
extension = new EllipticCurvesExtension(s, extlen);
|
extension = new SupportedGroupsExtension(s, extlen);
|
||||||
} else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) {
|
} else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) {
|
||||||
extension = new EllipticPointFormatsExtension(s, extlen);
|
extension = new EllipticPointFormatsExtension(s, extlen);
|
||||||
} else if (extType == ExtensionType.EXT_RENEGOTIATION_INFO) {
|
} else if (extType == ExtensionType.EXT_RENEGOTIATION_INFO) {
|
||||||
|
169
jdk/src/java.base/share/classes/sun/security/ssl/NamedGroup.java
Normal file
169
jdk/src/java.base/share/classes/sun/security/ssl/NamedGroup.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -96,7 +96,7 @@ final class ServerHandshaker extends Handshaker {
|
|||||||
private ProtocolVersion clientRequestedVersion;
|
private ProtocolVersion clientRequestedVersion;
|
||||||
|
|
||||||
// client supported elliptic curves
|
// client supported elliptic curves
|
||||||
private EllipticCurvesExtension requestedCurves;
|
private SupportedGroupsExtension requestedGroups;
|
||||||
|
|
||||||
// the preferable signature algorithm used by ServerKeyExchange message
|
// the preferable signature algorithm used by ServerKeyExchange message
|
||||||
SignatureAndHashAlgorithm preferableSignatureAlgorithm;
|
SignatureAndHashAlgorithm preferableSignatureAlgorithm;
|
||||||
@ -751,8 +751,8 @@ final class ServerHandshaker extends Handshaker {
|
|||||||
throw new SSLException("Client did not resume a session");
|
throw new SSLException("Client did not resume a session");
|
||||||
}
|
}
|
||||||
|
|
||||||
requestedCurves = (EllipticCurvesExtension)
|
requestedGroups = (SupportedGroupsExtension)
|
||||||
mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES);
|
mesg.extensions.get(ExtensionType.EXT_SUPPORTED_GROUPS);
|
||||||
|
|
||||||
// We only need to handle the "signature_algorithm" extension
|
// We only need to handle the "signature_algorithm" extension
|
||||||
// for full handshakes and TLS 1.2 or later.
|
// for full handshakes and TLS 1.2 or later.
|
||||||
@ -1341,6 +1341,8 @@ final class ServerHandshaker extends Handshaker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The named group used for ECDHE and FFDHE.
|
||||||
|
NamedGroup namedGroup = null;
|
||||||
switch (keyExchange) {
|
switch (keyExchange) {
|
||||||
case K_RSA:
|
case K_RSA:
|
||||||
// need RSA certs for authentication
|
// need RSA certs for authentication
|
||||||
@ -1366,6 +1368,37 @@ final class ServerHandshaker extends Handshaker {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case K_DHE_RSA:
|
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
|
// need RSA certs for authentication
|
||||||
if (setupPrivateKeyAndChain("RSA") == false) {
|
if (setupPrivateKeyAndChain("RSA") == false) {
|
||||||
return false;
|
return false;
|
||||||
@ -1386,9 +1419,20 @@ final class ServerHandshaker extends Handshaker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setupEphemeralDHKeys(suite.exportable, privateKey);
|
setupEphemeralDHKeys(namedGroup, suite.exportable, privateKey);
|
||||||
break;
|
break;
|
||||||
case K_ECDHE_RSA:
|
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
|
// need RSA certs for authentication
|
||||||
if (setupPrivateKeyAndChain("RSA") == false) {
|
if (setupPrivateKeyAndChain("RSA") == false) {
|
||||||
return false;
|
return false;
|
||||||
@ -1409,11 +1453,23 @@ final class ServerHandshaker extends Handshaker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setupEphemeralECDHKeys() == false) {
|
setupEphemeralECDHKeys(namedGroup);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case K_DHE_DSS:
|
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
|
// get preferable peer signature algorithm for server key exchange
|
||||||
if (protocolVersion.useTLS12PlusSpec()) {
|
if (protocolVersion.useTLS12PlusSpec()) {
|
||||||
preferableSignatureAlgorithm =
|
preferableSignatureAlgorithm =
|
||||||
@ -1434,9 +1490,20 @@ final class ServerHandshaker extends Handshaker {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setupEphemeralDHKeys(suite.exportable, privateKey);
|
setupEphemeralDHKeys(namedGroup, suite.exportable, privateKey);
|
||||||
break;
|
break;
|
||||||
case K_ECDHE_ECDSA:
|
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
|
// get preferable peer signature algorithm for server key exchange
|
||||||
if (protocolVersion.useTLS12PlusSpec()) {
|
if (protocolVersion.useTLS12PlusSpec()) {
|
||||||
preferableSignatureAlgorithm =
|
preferableSignatureAlgorithm =
|
||||||
@ -1456,9 +1523,8 @@ final class ServerHandshaker extends Handshaker {
|
|||||||
if (setupPrivateKeyAndChain("EC") == false) {
|
if (setupPrivateKeyAndChain("EC") == false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (setupEphemeralECDHKeys() == false) {
|
|
||||||
return false;
|
setupEphemeralECDHKeys(namedGroup);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case K_ECDH_RSA:
|
case K_ECDH_RSA:
|
||||||
// need EC cert
|
// need EC cert
|
||||||
@ -1475,14 +1541,36 @@ final class ServerHandshaker extends Handshaker {
|
|||||||
setupStaticECDHKeys();
|
setupStaticECDHKeys();
|
||||||
break;
|
break;
|
||||||
case K_DH_ANON:
|
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
|
// no certs needed for anonymous
|
||||||
setupEphemeralDHKeys(suite.exportable, null);
|
setupEphemeralDHKeys(namedGroup, suite.exportable, null);
|
||||||
break;
|
break;
|
||||||
case K_ECDH_ANON:
|
case K_ECDH_ANON:
|
||||||
// no certs needed for anonymous
|
// Is ECDHE cipher suite usable for the connection?
|
||||||
if (setupEphemeralECDHKeys() == false) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// no certs needed for anonymous
|
||||||
|
setupEphemeralECDHKeys(namedGroup);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ClientKeyExchangeService p =
|
ClientKeyExchangeService p =
|
||||||
@ -1544,7 +1632,15 @@ final class ServerHandshaker extends Handshaker {
|
|||||||
* Acquire some "ephemeral" Diffie-Hellman keys for this handshake.
|
* Acquire some "ephemeral" Diffie-Hellman keys for this handshake.
|
||||||
* We don't reuse these, for improved forward secrecy.
|
* 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
|
* 768 bits ephemeral DH private keys were used to be used in
|
||||||
* ServerKeyExchange except that exportable ciphers max out at 512
|
* ServerKeyExchange except that exportable ciphers max out at 512
|
||||||
@ -1613,20 +1709,11 @@ final class ServerHandshaker extends Handshaker {
|
|||||||
dh = new DHCrypt(keySize, sslContext.getSecureRandom());
|
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
|
* Setup the ephemeral ECDH parameters.
|
||||||
// the client requested, return false. Otherwise (all is well), return true.
|
*/
|
||||||
private boolean setupEphemeralECDHKeys() {
|
private void setupEphemeralECDHKeys(NamedGroup namedGroup) {
|
||||||
int index = (requestedCurves != null) ?
|
ecdh = new ECDHCrypt(namedGroup, sslContext.getSecureRandom());
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupStaticECDHKeys() {
|
private void setupStaticECDHKeys() {
|
||||||
@ -1674,9 +1761,11 @@ final class ServerHandshaker extends Handshaker {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
|
ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
|
||||||
int id = EllipticCurvesExtension.getCurveIndex(params);
|
NamedGroup namedGroup = NamedGroup.valueOf(params);
|
||||||
if ((id <= 0) || !EllipticCurvesExtension.isSupported(id) ||
|
if ((namedGroup == null) ||
|
||||||
((requestedCurves != null) && !requestedCurves.contains(id))) {
|
(!SupportedGroupsExtension.supports(namedGroup)) ||
|
||||||
|
((requestedGroups != null) &&
|
||||||
|
!requestedGroups.contains(namedGroup.id))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -31,33 +31,44 @@
|
|||||||
* @bug 6956398
|
* @bug 6956398
|
||||||
* @summary make ephemeral DH key match the length of the certificate key
|
* @summary make ephemeral DH key match the length of the certificate key
|
||||||
* @run main/othervm
|
* @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
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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
|
* DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5 false 357 139
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user