Improve parameters cache organization JDK-8171279-XDH-TLS-branch-2
authorapetcher
Fri, 17 Aug 2018 13:40:17 -0400
branchJDK-8171279-XDH-TLS-branch-2
changeset 56862 b9f6f8606065
parent 56861 3c83db004067
child 56863 c9d3ea14d270
Improve parameters cache organization
src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java
--- a/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java	Fri Aug 17 11:40:29 2018 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java	Fri Aug 17 13:40:17 2018 -0400
@@ -43,7 +43,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumSet;
-import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
@@ -162,7 +162,7 @@
         }
     }
 
-    static enum NamedGroupType {
+    enum NamedGroupType {
         NAMED_GROUP_ECDHE,          // Elliptic Curve Groups (ECDHE)
         NAMED_GROUP_FFDHE,          // Finite Field Groups (DHE)
         NAMED_GROUP_XDH,            // Finite Field Groups (XDH)
@@ -180,38 +180,64 @@
         }
     }
 
-    interface NamedGroupFunctions {
-
-        SSLKeyAgreementCredentials decodeCredentials(byte[] encoded)
-            throws IOException, GeneralSecurityException;
-
-        SSLPossession createPossession(SecureRandom random);
+    public static abstract class NamedGroupFunctions {
 
-        SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
-            throws IOException;
-
-        AlgorithmParameterSpec getParameterSpec();
-
-        boolean isAvailable();
-    }
-
-    private static class FFDHFunctions implements NamedGroupFunctions {
+        // cache to speed up the parameters construction
+        protected static final Map<NamedGroup, AlgorithmParameters>
+            namedGroupParams = new ConcurrentHashMap<>();
 
         private final NamedGroup ng;
 
+        protected NamedGroupFunctions(NamedGroup ng) {
+            this.ng = ng;
+        }
+
+        public AlgorithmParameters getParameters() {
+            AlgorithmParameters result = namedGroupParams.get(ng);
+            if (result == null) {
+                Optional<AlgorithmParameters> paramsOpt = getParametersImpl();
+                if (paramsOpt.isPresent()) {
+                    result = paramsOpt.get();
+                    namedGroupParams.put(ng, result);
+                }
+            }
+            return result;
+        }
+
+        public NamedGroup getNamedGroup() {
+            return ng;
+        }
+
+        public abstract SSLKeyAgreementCredentials decodeCredentials(byte[] encoded)
+            throws IOException, GeneralSecurityException;
+
+        public abstract  SSLPossession createPossession(SecureRandom random);
+
+        public abstract  SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
+            throws IOException;
+
+        protected abstract Optional<AlgorithmParameters> getParametersImpl();
+        public abstract AlgorithmParameterSpec getParameterSpec();
+
+        public abstract boolean isAvailable();
+    }
+
+    private static class FFDHFunctions extends NamedGroupFunctions {
+
+
         FFDHFunctions(NamedGroup ng) {
-            this.ng = ng;
+            super(ng);
         }
 
         @Override
         public SSLKeyAgreementCredentials decodeCredentials(byte[] encoded)
                 throws IOException, GeneralSecurityException {
-            return DHKeyExchange.DHECredentials.valueOf(ng, encoded);
+            return DHKeyExchange.DHECredentials.valueOf(getNamedGroup(), encoded);
         }
 
         @Override
         public SSLPossession createPossession(SecureRandom random) {
-            return new DHKeyExchange.DHEPossession(ng, random);
+            return new DHKeyExchange.DHEPossession(getNamedGroup(), random);
         }
 
         @Override
@@ -222,21 +248,17 @@
 
         @Override
         public AlgorithmParameterSpec getParameterSpec() {
-            return getDHParameterSpec(ng);
+            return getDHParameterSpec();
         }
 
-        static DHParameterSpec getDHParameterSpec(NamedGroup namedGroup) {
-            if (namedGroup.type != NamedGroupType.NAMED_GROUP_FFDHE) {
-                throw new RuntimeException(
-                    "Not a named DH group: " + namedGroup);
-            }
+        DHParameterSpec getDHParameterSpec() {
 
-            AlgorithmParameters params = SupportedGroups.namedGroupParams.get(namedGroup);
+            AlgorithmParameters params = getParameters();
             try {
                 return params.getParameterSpec(DHParameterSpec.class);
             } catch (InvalidParameterSpecException ipse) {
                 // should be unlikely
-                return getPredefinedDHParameterSpec(namedGroup);
+                return getPredefinedDHParameterSpec(getNamedGroup());
             }
         }
 
@@ -292,34 +314,42 @@
         public boolean isAvailable() {
 
             try {
-                AlgorithmParameters params = JsseJce.getAlgorithmParameters("DiffieHellman");
-                AlgorithmParameterSpec spec = getFFDHEDHParameterSpec(ng);
+                AlgorithmParameters params = getParameters();
+                AlgorithmParameterSpec spec = getFFDHEDHParameterSpec(getNamedGroup());
                 params.init(spec);
-                SupportedGroups.putNamedGroupParams(ng, params);
                 return true;
-            } catch (NoSuchAlgorithmException | InvalidParameterSpecException e) {
+            } catch (InvalidParameterSpecException e) {
                 return false;
             }
         }
+
+        @Override
+        protected Optional<AlgorithmParameters> getParametersImpl() {
+            try {
+                return Optional.of(
+                    JsseJce.getAlgorithmParameters("DiffieHellman"));
+            } catch(NoSuchAlgorithmException ex) {
+                return Optional.empty();
+            }
+        }
+
     }
 
-    private static class ECDHFunctions implements NamedGroupFunctions {
-
-        private final NamedGroup ng;
+    private static class ECDHFunctions extends NamedGroupFunctions {
 
         ECDHFunctions(NamedGroup ng) {
-            this.ng = ng;
+            super(ng);
         }
 
         @Override
         public SSLKeyAgreementCredentials decodeCredentials(byte[] encoded)
         throws IOException, GeneralSecurityException {
-            return ECDHKeyExchange.ECDHECredentials.valueOf(ng, encoded);
+            return ECDHKeyExchange.ECDHECredentials.valueOf(getNamedGroup(), encoded);
         }
 
         @Override
         public SSLPossession createPossession(SecureRandom random) {
-            return new ECDHKeyExchange.ECDHEPossession(ng, random);
+            return new ECDHKeyExchange.ECDHEPossession(getNamedGroup(), random);
         }
 
         @Override
@@ -330,41 +360,48 @@
 
         @Override
         public AlgorithmParameterSpec getParameterSpec() {
-            return SupportedGroups.getECGenParamSpec(ng);
+            return SupportedGroups.getECGenParamSpec(getNamedGroup());
         }
 
         @Override
         public boolean isAvailable() {
 
             try {
-                AlgorithmParameters params = JsseJce.getAlgorithmParameters("EC");
-                AlgorithmParameterSpec spec = new ECGenParameterSpec(ng.oid);
+                AlgorithmParameters params = getParameters();
+                AlgorithmParameterSpec spec = new ECGenParameterSpec(getNamedGroup().oid);
                 params.init(spec);
-                SupportedGroups.putNamedGroupParams(ng, params);
                 return true;
-            } catch (NoSuchAlgorithmException | InvalidParameterSpecException e) {
+            } catch (InvalidParameterSpecException e) {
                 return false;
             }
         }
+
+        @Override
+        protected Optional<AlgorithmParameters> getParametersImpl() {
+            try {
+                return Optional.of(
+                    JsseJce.getAlgorithmParameters("EC"));
+            } catch(NoSuchAlgorithmException ex) {
+                return Optional.empty();
+            }
+        }
     }
 
-    private static class XDHFunctions implements NamedGroupFunctions {
-
-        private final NamedGroup ng;
+    private static class XDHFunctions extends NamedGroupFunctions {
 
         XDHFunctions(NamedGroup ng) {
-            this.ng = ng;
+            super(ng);
         }
 
         @Override
         public SSLKeyAgreementCredentials decodeCredentials(byte[] encoded)
                 throws IOException, GeneralSecurityException {
-            return XDHKeyExchange.XDHECredentials.valueOf(ng, encoded);
+            return XDHKeyExchange.XDHECredentials.valueOf(getNamedGroup(), encoded);
         }
 
         @Override
         public SSLPossession createPossession(SecureRandom random) {
-            return new XDHKeyExchange.XDHEPossession(ng, random);
+            return new XDHKeyExchange.XDHEPossession(getNamedGroup(), random);
         }
 
         @Override
@@ -375,19 +412,24 @@
 
         @Override
         public AlgorithmParameterSpec getParameterSpec() {
-            return new NamedParameterSpec(ng.algorithm);
+            return new NamedParameterSpec(getNamedGroup().algorithm);
         }
 
         @Override
         public boolean isAvailable() {
 
             try {
-                JsseJce.getKeyAgreement(ng.algorithm);
+                JsseJce.getKeyAgreement(getNamedGroup().algorithm);
                 return true;
             } catch (NoSuchAlgorithmException ex) {
                 return false;
             }
         }
+
+        @Override
+        protected Optional<AlgorithmParameters> getParametersImpl() {
+            return Optional.empty();
+        }
     }
 
     static enum NamedGroup {
@@ -590,15 +632,14 @@
         }
 
         static NamedGroup valueOf(DHParameterSpec params) {
-            for (Map.Entry<NamedGroup, AlgorithmParameters> me :
-                    SupportedGroups.namedGroupParams.entrySet()) {
-                NamedGroup ng = me.getKey();
+            for (NamedGroup ng : NamedGroup.values()) {
                 if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) {
                     continue;
                 }
 
                 DHParameterSpec ngParams = null;
-                AlgorithmParameters aps = me.getValue();
+                // functions is non-null for FFDHE type
+                AlgorithmParameters aps = ng.functions.getParameters();
                 try {
                     ngParams = aps.getParameterSpec(DHParameterSpec.class);
                 } catch (InvalidParameterSpecException ipse) {
@@ -669,7 +710,10 @@
 
         // lazy loading of parameters
         AlgorithmParameters getParameters() {
-            return SupportedGroups.namedGroupParams.get(this);
+            if (functions == null) {
+                return null;
+            }
+            return functions.getParameters();
         }
 
         AlgorithmParameterSpec getParameterSpec() {
@@ -686,10 +730,6 @@
         static final boolean enableFFDHE =
                 Utilities.getBooleanProperty("jsse.enableFFDHE", true);
 
-        // cache to speed up the parameters construction
-        static final Map<NamedGroup,
-                    AlgorithmParameters> namedGroupParams = new HashMap<>();
-
         // the supported named groups
         static final NamedGroup[] supportedNamedGroups;
 
@@ -817,18 +857,14 @@
 
         }
 
-        static void putNamedGroupParams(NamedGroup ng,
-                                        AlgorithmParameters params) {
-            namedGroupParams.put(ng, params);
-        }
-
         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);
+            // functions is non-null for ECDHE type
+            AlgorithmParameters params = namedGroup.functions.getParameters();
             try {
                 return params.getParameterSpec(ECGenParameterSpec.class);
             } catch (InvalidParameterSpecException ipse) {
@@ -837,6 +873,14 @@
             }
         }
 
+        static AlgorithmParameters getParameters(NamedGroup ng) {
+            AlgorithmParameters params = null;
+            if (ng.functions != null) {
+                params = ng.functions.getParameters();
+            }
+            return params;
+        }
+
         // Is there any supported group permitted by the constraints?
         static boolean isActivatable(
                 AlgorithmConstraints constraints, NamedGroupType type) {
@@ -847,7 +891,7 @@
                     if (constraints.permits(
                             EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
                             namedGroup.algorithm,
-                            namedGroupParams.get(namedGroup))) {
+                            getParameters(namedGroup))) {
 
                         return true;
                     }
@@ -878,7 +922,7 @@
             return constraints.permits(
                             EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
                             namedGroup.algorithm,
-                            namedGroupParams.get(namedGroup));
+                            getParameters(namedGroup));
         }
 
         // Is there any supported group permitted by the constraints?
@@ -902,7 +946,7 @@
                         constraints.permits(
                                 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
                                 namedGroup.algorithm,
-                                namedGroupParams.get(namedGroup))) {
+                                getParameters(namedGroup))) {
                     return namedGroup;
                 }
             }
@@ -919,7 +963,7 @@
                         constraints.permits(
                                 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
                                 namedGroup.algorithm,
-                                namedGroupParams.get(namedGroup))) {
+                                getParameters(namedGroup))) {
                     return namedGroup;
                 }
             }
@@ -967,7 +1011,7 @@
                         ng.isSupported(chc.activeCipherSuites) &&
                         chc.algorithmConstraints.permits(
                             EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                            ng.algorithm, namedGroupParams.get(ng))) {
+                            ng.algorithm, getParameters(ng))) {
                     namedGroups.add(ng);
                 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
                     SSLLogger.fine(
@@ -1095,7 +1139,7 @@
                         ng.isSupported(shc.activeCipherSuites) &&
                         shc.algorithmConstraints.permits(
                             EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                            ng.algorithm, namedGroupParams.get(ng))) {
+                            ng.algorithm, getParameters(ng))) {
                     namedGroups.add(ng);
                 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
                     SSLLogger.fine(