changeset 1784:daf336ae76e3

8178728: Check the AlgorithmParameters in algorithm constraints Reviewed-by: valeriep, ascarpino
author igerasim
date Thu, 08 Jun 2017 14:01:12 -0700
parents f503cd2e97ad
children 9d464511a79e
files src/share/classes/sun/security/util/AlgorithmDecomposer.java src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java src/share/classes/sun/security/util/KeyUtil.java
diffstat 3 files changed, 146 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/sun/security/util/AlgorithmDecomposer.java	Mon Dec 04 16:24:30 2017 -0800
+++ b/src/share/classes/sun/security/util/AlgorithmDecomposer.java	Thu Jun 08 14:01:12 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -27,6 +27,8 @@
 
 import java.util.HashSet;
 import java.util.Set;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.regex.Pattern;
 
 /**
@@ -133,6 +135,23 @@
         return elements;
     }
 
+    /**
+     * Get aliases of the specified algorithm.
+     *
+     * May support more algorithms in the future.
+     */
+    public static Collection<String> getAliases(String algorithm) {
+        String[] aliases;
+        if (algorithm.equalsIgnoreCase("DH") ||
+                algorithm.equalsIgnoreCase("DiffieHellman")) {
+            aliases = new String[] {"DH", "DiffieHellman"};
+        } else {
+            aliases = new String[] {algorithm};
+        }
+
+        return Arrays.asList(aliases);
+    }
+
     private static void hasLoop(Set<String> elements, String find, String replace) {
         if (elements.contains(find)) {
             if (!elements.contains(replace)) {
--- a/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Mon Dec 04 16:24:30 2017 -0800
+++ b/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Thu Jun 08 14:01:12 2017 -0700
@@ -94,7 +94,15 @@
     @Override
     public final boolean permits(Set<CryptoPrimitive> primitives,
             String algorithm, AlgorithmParameters parameters) {
-        return checkAlgorithm(disabledAlgorithms, algorithm, decomposer);
+        if (!checkAlgorithm(disabledAlgorithms, algorithm, decomposer)) {
+            return false;
+        }
+
+        if (parameters != null) {
+            return algorithmConstraints.permits(algorithm, parameters);
+        }
+
+        return true;
     }
 
     /*
@@ -232,6 +240,13 @@
                     constraintList = new ArrayList<Constraint>(1);
                     constraintsMap.put(algorithm, constraintList);
                 }
+                // Consider the impact of algorithm aliases.
+                for (String alias : AlgorithmDecomposer.getAliases(algorithm)) {
+                    if (constraintsMap.get(alias) == null) {
+                        constraintsMap.put(alias, constraintList);
+                    }
+                }
+
                 if (space <= 0) {
                     constraintList.add(new DisabledConstraint(algorithm));
                     continue;
@@ -339,6 +354,27 @@
             return true;
         }
 
+        // Check if constraints permit this AlgorithmParameters.
+        public boolean permits(String algorithm, AlgorithmParameters aps) {
+            List<Constraint> list = getConstraints(algorithm);
+            if (list == null) {
+                return true;
+            }
+
+            for (Constraint constraint : list) {
+                if (!constraint.permits(aps)) {
+                    if (debug != null) {
+                        debug.println("keySizeConstraint: failed algorithm " +
+                                "parameters constraint check " + aps);
+                    }
+
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
         // Check if constraints permit this cert.
         public void permits(String algorithm, ConstraintsParameters cp)
                 throws CertPathValidatorException {
@@ -431,6 +467,18 @@
         }
 
         /**
+         * Check if the algorithm constraint permits a given cryptographic
+         * parameters.
+         *
+         * @param parameters the cryptographic parameters
+         * @return 'true' if the cryptographic parameters is allowed,
+         *         'false' ortherwise.
+         */
+        public boolean permits(AlgorithmParameters parameters) {
+            return true;
+        }
+
+        /**
          * Check if an algorithm constraint is permitted with a given
          * ConstraintsParameters.
          *
@@ -514,6 +562,7 @@
          * call next() for any following constraints. If it does not, exit
          * as this constraint(s) does not restrict the operation.
          */
+        @Override
         public void permits(ConstraintsParameters cp)
                 throws CertPathValidatorException {
             if (debug != null) {
@@ -642,6 +691,7 @@
             this.usages = usages;
         }
 
+        @Override
         public void permits(ConstraintsParameters cp)
                 throws CertPathValidatorException {
             for (String usage : usages) {
@@ -729,6 +779,7 @@
          * constraint  Any permitted constraint will exit the linked list
          * to allow the operation.
          */
+        @Override
         public void permits(ConstraintsParameters cp)
 	    throws CertPathValidatorException {
             Key key = null;
@@ -751,6 +802,7 @@
 
         // Check if key constraint disable the specified key
         // Uses old style permit()
+        @Override
         public boolean permits(Key key) {
             // If we recursively find a constraint that permits us to use
             // this key, return true and skip any other constraint checks.
@@ -764,6 +816,30 @@
             return permitsImpl(key);
         }
 
+        @Override
+        public boolean permits(AlgorithmParameters parameters) {
+            String paramAlg = parameters.getAlgorithm();
+            if (!algorithm.equalsIgnoreCase(parameters.getAlgorithm())) {
+                // Consider the impact of the algorithm aliases.
+                Collection<String> aliases =
+                        AlgorithmDecomposer.getAliases(algorithm);
+                if (!aliases.contains(paramAlg)) {
+                    return true;
+                }
+            }
+
+            int keySize = KeyUtil.getKeySize(parameters);
+            if (keySize == 0) {
+                return false;
+            } else if (keySize > 0) {
+                return !((keySize < minSize) || (keySize > maxSize) ||
+                    (prohibitedSize == keySize));
+            }   // Otherwise, the key size is not accessible or determined.
+                // Conservatively, please don't disable such keys.
+
+            return true;
+        }
+
         private boolean permitsImpl(Key key) {
             // Verify this constraint is for this public key algorithm
             if (algorithm.compareToIgnoreCase(key.getAlgorithm()) != 0) {
@@ -792,6 +868,7 @@
             algorithm = algo;
         }
 
+        @Override
         public void permits(ConstraintsParameters cp)
                 throws CertPathValidatorException {
                        throw new CertPathValidatorException(
@@ -799,6 +876,7 @@
                                        "algorithm: " + algorithm + extendedMsg(cp));
         }
 
+        @Override
         public boolean permits(Key key) {
             return false;
         }
--- a/src/share/classes/sun/security/util/KeyUtil.java	Mon Dec 04 16:24:30 2017 -0800
+++ b/src/share/classes/sun/security/util/KeyUtil.java	Thu Jun 08 14:01:12 2017 -0700
@@ -6,6 +6,7 @@
 
 package sun.security.util;
 
+import java.security.AlgorithmParameters;
 import java.security.Key;
 import java.security.PrivilegedAction;
 import java.security.AccessController;
@@ -16,6 +17,8 @@
 import java.security.interfaces.DSAParams;
 import java.security.SecureRandom;
 import java.security.spec.KeySpec;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
 import javax.crypto.SecretKey;
 import javax.crypto.interfaces.DHKey;
 import javax.crypto.interfaces.DHPublicKey;
@@ -81,6 +84,50 @@
     }
 
     /**
+     * Returns the key size of the given cryptographic parameters in bits.
+     *
+     * @param parameters the cryptographic parameters, cannot be null
+     * @return the key size of the given cryptographic parameters in bits,
+     *       or -1 if the key size is not accessible
+     */
+    public static final int getKeySize(AlgorithmParameters parameters) {
+
+        String algorithm = parameters.getAlgorithm();
+        if (algorithm.equals("EC")) {
+            try {
+                ECParameterSpec ps = parameters.getParameterSpec(
+                        ECParameterSpec.class);
+                if (ps != null) {
+                    return ps.getOrder().bitLength();
+                }
+            } catch (InvalidParameterSpecException ipse) {
+                // ignore
+            }
+
+            // Note: the ECGenParameterSpec case should be covered by the
+            // ECParameterSpec case above.
+            // See ECUtil.getECParameterSpec(Provider, String).
+
+
+        } else if (algorithm.equals("DiffieHellman")) {
+            try {
+                DHParameterSpec ps = parameters.getParameterSpec(
+                        DHParameterSpec.class);
+                if (ps != null) {
+                    return ps.getP().bitLength();
+                }
+            } catch (InvalidParameterSpecException ipse) {
+                // ignore
+            }
+
+
+            // May support more AlgorithmParameters algorithms in the future.
+        }
+
+        return -1;
+    }
+
+    /**
      * Returns whether the key is valid or not.
      * <P>
      * Note that this method is only apply to DHPublicKey at present.