< prev index next >

src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java

Print this page
rev 14231 : 8233228: Disable weak named curves by default in TLS, CertPath, and Signed JAR
Reviewed-by: mullan, xuelei, weijun
   1 /*
   2  * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  43 import java.util.HashSet;
  44 import java.util.List;
  45 import java.util.Locale;
  46 import java.util.Map;
  47 import java.util.Set;
  48 import java.util.Collection;
  49 import java.util.StringTokenizer;
  50 import java.util.TimeZone;
  51 import java.util.regex.Pattern;
  52 import java.util.regex.Matcher;
  53 
  54 /**
  55  * Algorithm constraints for disabled algorithms property
  56  *
  57  * See the "jdk.certpath.disabledAlgorithms" specification in java.security
  58  * for the syntax of the disabled algorithm string.
  59  */
  60 public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
  61     private static final Debug debug = Debug.getInstance("certpath");
  62 
  63     // the known security property, jdk.certpath.disabledAlgorithms
  64     public static final String PROPERTY_CERTPATH_DISABLED_ALGS =
  65             "jdk.certpath.disabledAlgorithms";
  66 
  67     // the known security property, jdk.tls.disabledAlgorithms
  68     public static final String PROPERTY_TLS_DISABLED_ALGS =
  69             "jdk.tls.disabledAlgorithms";
  70 
  71     // the known security property, jdk.jar.disabledAlgorithms
  72     public static final String PROPERTY_JAR_DISABLED_ALGS =
  73             "jdk.jar.disabledAlgorithms";
  74 
  75     private final String[] disabledAlgorithms;




  76     private final Constraints algorithmConstraints;
  77 
  78     /**
  79      * Initialize algorithm constraints with the specified security property.
  80      *
  81      * @param propertyName the security property name that define the disabled
  82      *        algorithm constraints
  83      */
  84     public DisabledAlgorithmConstraints(String propertyName) {
  85         this(propertyName, new AlgorithmDecomposer());
  86     }
  87 
  88     /**
  89      * Initialize algorithm constraints with the specified security property
  90      * for a specific usage type.
  91      *
  92      * @param propertyName the security property name that define the disabled
  93      *        algorithm constraints
  94      * @param decomposer an alternate AlgorithmDecomposer.
  95      */
  96     public DisabledAlgorithmConstraints(String propertyName,
  97             AlgorithmDecomposer decomposer) {
  98         super(decomposer);
  99         disabledAlgorithms = getAlgorithms(propertyName);


















 100         algorithmConstraints = new Constraints(disabledAlgorithms);
 101     }
 102 
 103     /*
 104      * This only checks if the algorithm has been completely disabled.  If
 105      * there are keysize or other limit, this method allow the algorithm.
 106      */
 107     @Override
 108     public final boolean permits(Set<CryptoPrimitive> primitives,
 109             String algorithm, AlgorithmParameters parameters) {
 110         if (!checkAlgorithm(disabledAlgorithms, algorithm, decomposer)) {
 111             return false;
 112         }
 113 
 114         if (parameters != null) {
 115             return algorithmConstraints.permits(algorithm, parameters);
 116         }
 117 
 118         return true;
 119     }


 147         permits(cp.getAlgorithm(), cp);
 148     }
 149 
 150     public final void permits(String algorithm, Key key,
 151             AlgorithmParameters params, String variant)
 152             throws CertPathValidatorException {
 153         permits(algorithm, new ConstraintsParameters(algorithm, params, key,
 154                 (variant == null) ? Validator.VAR_GENERIC : variant));
 155     }
 156 
 157     /*
 158      * Check if a x509Certificate object is permitted.  Check if all
 159      * algorithms are allowed, certificate constraints, and the
 160      * public key against key constraints.
 161      *
 162      * Uses new style permit() which throws exceptions.
 163      */
 164 
 165     public final void permits(String algorithm, ConstraintsParameters cp)
 166             throws CertPathValidatorException {













 167         algorithmConstraints.permits(algorithm, cp);
 168     }
 169 
 170     // Check if a string is contained inside the property
 171     public boolean checkProperty(String param) {
 172         param = param.toLowerCase(Locale.ENGLISH);
 173         for (String block : disabledAlgorithms) {
 174             if (block.toLowerCase(Locale.ENGLISH).indexOf(param) >= 0) {
 175                 return true;
 176             }
 177         }
 178         return false;
 179     }
 180 
 181     // Check algorithm constraints with key and algorithm
 182     private boolean checkConstraints(Set<CryptoPrimitive> primitives,
 183             String algorithm, Key key, AlgorithmParameters parameters) {
 184 
 185         // check the key parameter, it cannot be null.
 186         if (key == null) {
 187             throw new IllegalArgumentException("The key cannot be null");
 188         }
 189 
 190         // check the signature algorithm with parameters
 191         if (algorithm != null && algorithm.length() != 0) {
 192             if (!permits(primitives, algorithm, parameters)) {
 193                 return false;
 194             }
 195         }
 196 
 197         // check the key algorithm
 198         if (!permits(primitives, key.getAlgorithm(), null)) {
 199             return false;
 200         }
 201 







 202         // check the key constraints
 203         return algorithmConstraints.permits(key);
 204     }
 205 
 206 
 207     /**
 208      * Key and Certificate Constraints
 209      *
 210      * The complete disabling of an algorithm is not handled by Constraints or
 211      * Constraint classes.  That is addressed with
 212      *   permit(Set<CryptoPrimitive>, String, AlgorithmParameters)
 213      *
 214      * When passing a Key to permit(), the boolean return values follow the
 215      * same as the interface class AlgorithmConstraints.permit().  This is to
 216      * maintain compatibility:
 217      * 'true' means the operation is allowed.
 218      * 'false' means it failed the constraints and is disallowed.
 219      *
 220      * When passing ConstraintsParameters through permit(), an exception
 221      * will be thrown on a failure to better identify why the operation was
 222      * disallowed.
 223      */
 224 
 225     private static class Constraints {
 226         private Map<String, List<Constraint>> constraintsMap = new HashMap<>();
 227 
 228         private static class Holder {
 229             private static final Pattern DENY_AFTER_PATTERN = Pattern.compile(
 230                     "denyAfter\\s+(\\d{4})-(\\d{2})-(\\d{2})");
 231         }
 232 
 233         public Constraints(String[] constraintArray) {
 234             for (String constraintEntry : constraintArray) {
 235                 if (constraintEntry == null || constraintEntry.isEmpty()) {
 236                     continue;
 237                 }
 238 
 239                 constraintEntry = constraintEntry.trim();
 240                 if (debug != null) {
 241                     debug.println("Constraints: " + constraintEntry);
 242                 }
 243 
 244                 // Check if constraint is a complete disabling of an
 245                 // algorithm or has conditions.
 246                 int space = constraintEntry.indexOf(' ');
 247                 String algorithm = AlgorithmDecomposer.hashName(
 248                         ((space > 0 ? constraintEntry.substring(0, space) :
 249                                 constraintEntry)));
 250                 List<Constraint> constraintList =
 251                         constraintsMap.getOrDefault(
 252                                 algorithm.toUpperCase(Locale.ENGLISH),
 253                                 new ArrayList<>(1));
 254 
 255                 // Consider the impact of algorithm aliases.
 256                 for (String alias : AlgorithmDecomposer.getAliases(algorithm)) {
 257                     constraintsMap.putIfAbsent(
 258                             alias.toUpperCase(Locale.ENGLISH), constraintList);
 259                 }
 260 
 261                 if (space <= 0) {


 262                     constraintList.add(new DisabledConstraint(algorithm));
 263                     continue;
 264                 }
 265 
 266                 String policy = constraintEntry.substring(space + 1);
 267 
 268                 // Convert constraint conditions into Constraint classes
 269                 Constraint c, lastConstraint = null;
 270                 // Allow only one jdkCA entry per constraint entry
 271                 boolean jdkCALimit = false;
 272                 // Allow only one denyAfter entry per constraint entry
 273                 boolean denyAfterLimit = false;
 274 
 275                 for (String entry : policy.split("&")) {
 276                     entry = entry.trim();
 277 
 278                     Matcher matcher;
 279                     if (entry.startsWith("keySize")) {
 280                         if (debug != null) {
 281                             debug.println("Constraints set to keySize: " +


 340                     }
 341                     lastConstraint = c;
 342                 }
 343             }
 344         }
 345 
 346         // Get applicable constraints based off the signature algorithm
 347         private List<Constraint> getConstraints(String algorithm) {
 348             return constraintsMap.get(algorithm.toUpperCase(Locale.ENGLISH));
 349         }
 350 
 351         // Check if KeySizeConstraints permit the specified key
 352         public boolean permits(Key key) {
 353             List<Constraint> list = getConstraints(key.getAlgorithm());
 354             if (list == null) {
 355                 return true;
 356             }
 357             for (Constraint constraint : list) {
 358                 if (!constraint.permits(key)) {
 359                     if (debug != null) {
 360                         debug.println("keySizeConstraint: failed key " +
 361                                 "constraint check " + KeyUtil.getKeySize(key));
 362                     }
 363                     return false;
 364                 }
 365             }
 366             return true;
 367         }
 368 
 369         // Check if constraints permit this AlgorithmParameters.
 370         public boolean permits(String algorithm, AlgorithmParameters aps) {
 371             List<Constraint> list = getConstraints(algorithm);
 372             if (list == null) {
 373                 return true;
 374             }
 375 
 376             for (Constraint constraint : list) {
 377                 if (!constraint.permits(aps)) {
 378                     if (debug != null) {
 379                         debug.println("keySizeConstraint: failed algorithm " +
 380                                 "parameters constraint check " + aps);
 381                     }
 382 
 383                     return false;
 384                 }
 385             }
 386 
 387             return true;
 388         }
 389 
 390         // Check if constraints permit this cert.
 391         public void permits(String algorithm, ConstraintsParameters cp)
 392                 throws CertPathValidatorException {
 393             X509Certificate cert = cp.getCertificate();
 394 
 395             if (debug != null) {
 396                 debug.println("Constraints.permits(): " + algorithm +
 397                         " Variant: " + cp.getVariant());
 398             }
 399 
 400             // Get all signature algorithms to check for constraints
 401             Set<String> algorithms = new HashSet<>();
 402             if (algorithm != null) {
 403                 algorithms.addAll(AlgorithmDecomposer.decomposeOneHash(algorithm));
 404                 algorithms.add(algorithm);
 405             }
 406 
 407             // Attempt to add the public key algorithm if cert provided
 408             if (cert != null) {
 409                 algorithms.add(cert.getPublicKey().getAlgorithm());
 410             }
 411             if (cp.getPublicKey() != null) {
 412                 algorithms.add(cp.getPublicKey().getAlgorithm());
 413             }
 414             // Check all applicable constraints
 415             for (String alg : algorithms) {
 416                 List<Constraint> list = getConstraints(alg);
 417                 if (list == null) {
 418                     continue;
 419                 }
 420                 for (Constraint constraint : list) {
 421                     constraint.permits(cp);
 422                 }
 423             }
 424         }
 425     }
 426 
 427     /**
 428      * This abstract Constraint class for algorithm-based checking
 429      * may contain one or more constraints.  If the '&' on the {@Security}
 430      * property is used, multiple constraints have been grouped together
 431      * requiring all the constraints to fail for the check to be disallowed.
 432      *


 531                 return true;
 532             }
 533             return false;
 534         }
 535 
 536         /**
 537          * Recursively check if this constraint is allowed,
 538          *
 539          * If {@code nextConstraint} is non-null, this method will
 540          * call {@code nextConstraint}'s {@code permit()} to check if the
 541          * constraint is allowed or denied.  If the constraint's
 542          * {@code permit()} is allowed, this method will exit this and any
 543          * recursive next() calls, returning 'true'.  If the constraints
 544          * called were disallowed the check will exit with 'false'.
 545          *
 546          * @param key Public key
 547          * @return 'true' if constraint allows the operation, 'false' if
 548          * the constraint denies the operation.
 549          */
 550         boolean next(Key key) {
 551             if (nextConstraint != null && nextConstraint.permits(key)) {
 552                 return true;
 553             }
 554             return false;
 555         }
 556 
 557         String extendedMsg(ConstraintsParameters cp) {
 558             return (cp.getCertificate() == null ? "." :
 559                     " used with certificate: " +
 560                             cp.getCertificate().getSubjectX500Principal() +
 561                     (cp.getVariant() != Validator.VAR_GENERIC ?
 562                             ".  Usage was " + cp.getVariant() : "."));
 563         }
 564     }
 565 
 566     /*
 567      * This class contains constraints dealing with the certificate chain
 568      * of the certificate.
 569      */
 570     private static class jdkCAConstraint extends Constraint {
 571         jdkCAConstraint(String algo) {
 572             algorithm = algo;
 573         }
 574 


 786                     this.maxSize = length > 1 ? (length - 1) : 0;
 787                     break;
 788                 default:
 789                     // unlikely to happen
 790                     this.minSize = Integer.MAX_VALUE;
 791                     this.maxSize = -1;
 792             }
 793         }
 794 
 795         /*
 796          * If we are passed a certificate, extract the public key and use it.
 797          *
 798          * Check if each constraint fails and check if there is a linked
 799          * constraint  Any permitted constraint will exit the linked list
 800          * to allow the operation.
 801          */
 802         @Override
 803         public void permits(ConstraintsParameters cp)
 804                 throws CertPathValidatorException {
 805             Key key = null;
 806             if (cp.getPublicKey() != null) {
 807                 key = cp.getPublicKey();
 808             } else if (cp.getCertificate() != null) {
 809                 key = cp.getCertificate().getPublicKey();
 810             }
 811             if (key != null && !permitsImpl(key)) {
 812                 if (nextConstraint != null) {
 813                     nextConstraint.permits(cp);
 814                     return;
 815                 }
 816                 throw new CertPathValidatorException(
 817                         "Algorithm constraints check failed on keysize limits. " +
 818                         algorithm + " " + KeyUtil.getKeySize(key) + "bit key" +
 819                         extendedMsg(cp),
 820                         null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
 821             }
 822         }
 823 
 824 
 825         // Check if key constraint disable the specified key
 826         // Uses old style permit()
 827         @Override


   1 /*
   2  * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  43 import java.util.HashSet;
  44 import java.util.List;
  45 import java.util.Locale;
  46 import java.util.Map;
  47 import java.util.Set;
  48 import java.util.Collection;
  49 import java.util.StringTokenizer;
  50 import java.util.TimeZone;
  51 import java.util.regex.Pattern;
  52 import java.util.regex.Matcher;
  53 
  54 /**
  55  * Algorithm constraints for disabled algorithms property
  56  *
  57  * See the "jdk.certpath.disabledAlgorithms" specification in java.security
  58  * for the syntax of the disabled algorithm string.
  59  */
  60 public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
  61     private static final Debug debug = Debug.getInstance("certpath");
  62 
  63     // Disabled algorithm security property for certificate path
  64     public static final String PROPERTY_CERTPATH_DISABLED_ALGS =
  65             "jdk.certpath.disabledAlgorithms";
  66 
  67     // Disabled algorithm security property for TLS
  68     public static final String PROPERTY_TLS_DISABLED_ALGS =
  69             "jdk.tls.disabledAlgorithms";
  70 
  71     // Disabled algorithm security property for jar
  72     public static final String PROPERTY_JAR_DISABLED_ALGS =
  73             "jdk.jar.disabledAlgorithms";
  74 
  75     // Property for disabled EC named curves
  76     private static final String PROPERTY_DISABLED_EC_CURVES =
  77             "jdk.disabled.namedCurves";
  78 
  79     private final List<String> disabledAlgorithms;
  80     private final Constraints algorithmConstraints;
  81 
  82     /**
  83      * Initialize algorithm constraints with the specified security property.
  84      *
  85      * @param propertyName the security property name that define the disabled
  86      *        algorithm constraints
  87      */
  88     public DisabledAlgorithmConstraints(String propertyName) {
  89         this(propertyName, new AlgorithmDecomposer());
  90     }
  91 
  92     /**
  93      * Initialize algorithm constraints with the specified security property
  94      * for a specific usage type.
  95      *
  96      * @param propertyName the security property name that define the disabled
  97      *        algorithm constraints
  98      * @param decomposer an alternate AlgorithmDecomposer.
  99      */
 100     public DisabledAlgorithmConstraints(String propertyName,
 101             AlgorithmDecomposer decomposer) {
 102         super(decomposer);
 103         disabledAlgorithms = getAlgorithms(propertyName);
 104 
 105         // Check for alias
 106         int ecindex = -1, i = 0;
 107         for (String s : disabledAlgorithms) {
 108             if (s.regionMatches(true, 0,"include ", 0, 8)) {
 109                 if (s.regionMatches(true, 8, PROPERTY_DISABLED_EC_CURVES, 0,
 110                         PROPERTY_DISABLED_EC_CURVES.length())) {
 111                     ecindex = i;
 112                     break;
 113                 }
 114             }
 115             i++;
 116         }
 117         if (ecindex > -1) {
 118             disabledAlgorithms.remove(ecindex);
 119             disabledAlgorithms.addAll(ecindex,
 120                     getAlgorithms(PROPERTY_DISABLED_EC_CURVES));
 121         }
 122         algorithmConstraints = new Constraints(disabledAlgorithms);
 123     }
 124 
 125     /*
 126      * This only checks if the algorithm has been completely disabled.  If
 127      * there are keysize or other limit, this method allow the algorithm.
 128      */
 129     @Override
 130     public final boolean permits(Set<CryptoPrimitive> primitives,
 131             String algorithm, AlgorithmParameters parameters) {
 132         if (!checkAlgorithm(disabledAlgorithms, algorithm, decomposer)) {
 133             return false;
 134         }
 135 
 136         if (parameters != null) {
 137             return algorithmConstraints.permits(algorithm, parameters);
 138         }
 139 
 140         return true;
 141     }


 169         permits(cp.getAlgorithm(), cp);
 170     }
 171 
 172     public final void permits(String algorithm, Key key,
 173             AlgorithmParameters params, String variant)
 174             throws CertPathValidatorException {
 175         permits(algorithm, new ConstraintsParameters(algorithm, params, key,
 176                 (variant == null) ? Validator.VAR_GENERIC : variant));
 177     }
 178 
 179     /*
 180      * Check if a x509Certificate object is permitted.  Check if all
 181      * algorithms are allowed, certificate constraints, and the
 182      * public key against key constraints.
 183      *
 184      * Uses new style permit() which throws exceptions.
 185      */
 186 
 187     public final void permits(String algorithm, ConstraintsParameters cp)
 188             throws CertPathValidatorException {
 189 
 190         // Check if named curves in the ConstraintParameters are disabled.
 191         if (cp.getNamedCurve() != null) {
 192             for (String curve : cp.getNamedCurve()) {
 193                 if (!checkAlgorithm(disabledAlgorithms, curve, decomposer)) {
 194                     throw new CertPathValidatorException(
 195                             "Algorithm constraints check failed on disabled " +
 196                                     "algorithm: " + curve,
 197                             null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
 198                 }
 199             }
 200         }
 201 
 202         algorithmConstraints.permits(algorithm, cp);
 203     }
 204 
 205     // Check if a string is contained inside the property
 206     public boolean checkProperty(String param) {
 207         param = param.toLowerCase(Locale.ENGLISH);
 208         for (String block : disabledAlgorithms) {
 209             if (block.toLowerCase(Locale.ENGLISH).indexOf(param) >= 0) {
 210                 return true;
 211             }
 212         }
 213         return false;
 214     }
 215 
 216     // Check algorithm constraints with key and algorithm
 217     private boolean checkConstraints(Set<CryptoPrimitive> primitives,
 218             String algorithm, Key key, AlgorithmParameters parameters) {
 219 
 220         // check the key parameter, it cannot be null.
 221         if (key == null) {
 222             throw new IllegalArgumentException("The key cannot be null");
 223         }
 224 
 225         // check the signature algorithm with parameters
 226         if (algorithm != null && algorithm.length() != 0) {
 227             if (!permits(primitives, algorithm, parameters)) {
 228                 return false;
 229             }
 230         }
 231 
 232         // check the key algorithm
 233         if (!permits(primitives, key.getAlgorithm(), null)) {
 234             return false;
 235         }
 236 
 237         // If this is an elliptic curve, check disabled the named curve.
 238         for (String curve : ConstraintsParameters.getNamedCurveFromKey(key)) {
 239             if (!permits(primitives, curve, null)) {
 240                 return false;
 241             }
 242         }
 243 
 244         // check the key constraints
 245         return algorithmConstraints.permits(key);
 246     }
 247 
 248 
 249     /**
 250      * Key and Certificate Constraints
 251      *
 252      * The complete disabling of an algorithm is not handled by Constraints or
 253      * Constraint classes.  That is addressed with
 254      *   permit(Set<CryptoPrimitive>, String, AlgorithmParameters)
 255      *
 256      * When passing a Key to permit(), the boolean return values follow the
 257      * same as the interface class AlgorithmConstraints.permit().  This is to
 258      * maintain compatibility:
 259      * 'true' means the operation is allowed.
 260      * 'false' means it failed the constraints and is disallowed.
 261      *
 262      * When passing ConstraintsParameters through permit(), an exception
 263      * will be thrown on a failure to better identify why the operation was
 264      * disallowed.
 265      */
 266 
 267     private static class Constraints {
 268         private Map<String, List<Constraint>> constraintsMap = new HashMap<>();
 269 
 270         private static class Holder {
 271             private static final Pattern DENY_AFTER_PATTERN = Pattern.compile(
 272                     "denyAfter\\s+(\\d{4})-(\\d{2})-(\\d{2})");
 273         }
 274 
 275         public Constraints(List<String> constraintArray) {
 276             for (String constraintEntry : constraintArray) {
 277                 if (constraintEntry == null || constraintEntry.isEmpty()) {
 278                     continue;
 279                 }
 280 
 281                 constraintEntry = constraintEntry.trim();
 282                 if (debug != null) {
 283                     debug.println("Constraints: " + constraintEntry);
 284                 }
 285 
 286                 // Check if constraint is a complete disabling of an
 287                 // algorithm or has conditions.
 288                 int space = constraintEntry.indexOf(' ');
 289                 String algorithm = AlgorithmDecomposer.hashName(
 290                         ((space > 0 ? constraintEntry.substring(0, space) :
 291                                 constraintEntry)));
 292                 List<Constraint> constraintList =
 293                         constraintsMap.getOrDefault(
 294                                 algorithm.toUpperCase(Locale.ENGLISH),
 295                                 new ArrayList<>(1));
 296 
 297                 // Consider the impact of algorithm aliases.
 298                 for (String alias : AlgorithmDecomposer.getAliases(algorithm)) {
 299                     constraintsMap.putIfAbsent(
 300                             alias.toUpperCase(Locale.ENGLISH), constraintList);
 301                 }
 302 
 303                 // If there is no whitespace, it is a algorithm name; however,
 304                 // if there is a whitespace, could be a multi-word EC curve too.
 305                 if (space <= 0 || CurveDB.lookup(constraintEntry) != null) {
 306                     constraintList.add(new DisabledConstraint(algorithm));
 307                     continue;
 308                 }
 309 
 310                 String policy = constraintEntry.substring(space + 1);
 311 
 312                 // Convert constraint conditions into Constraint classes
 313                 Constraint c, lastConstraint = null;
 314                 // Allow only one jdkCA entry per constraint entry
 315                 boolean jdkCALimit = false;
 316                 // Allow only one denyAfter entry per constraint entry
 317                 boolean denyAfterLimit = false;
 318 
 319                 for (String entry : policy.split("&")) {
 320                     entry = entry.trim();
 321 
 322                     Matcher matcher;
 323                     if (entry.startsWith("keySize")) {
 324                         if (debug != null) {
 325                             debug.println("Constraints set to keySize: " +


 384                     }
 385                     lastConstraint = c;
 386                 }
 387             }
 388         }
 389 
 390         // Get applicable constraints based off the signature algorithm
 391         private List<Constraint> getConstraints(String algorithm) {
 392             return constraintsMap.get(algorithm.toUpperCase(Locale.ENGLISH));
 393         }
 394 
 395         // Check if KeySizeConstraints permit the specified key
 396         public boolean permits(Key key) {
 397             List<Constraint> list = getConstraints(key.getAlgorithm());
 398             if (list == null) {
 399                 return true;
 400             }
 401             for (Constraint constraint : list) {
 402                 if (!constraint.permits(key)) {
 403                     if (debug != null) {
 404                         debug.println("Constraints: failed key size" +
 405                                 "constraint check " + KeyUtil.getKeySize(key));
 406                     }
 407                     return false;
 408                 }
 409             }
 410             return true;
 411         }
 412 
 413         // Check if constraints permit this AlgorithmParameters.
 414         public boolean permits(String algorithm, AlgorithmParameters aps) {
 415             List<Constraint> list = getConstraints(algorithm);
 416             if (list == null) {
 417                 return true;
 418             }
 419 
 420             for (Constraint constraint : list) {
 421                 if (!constraint.permits(aps)) {
 422                     if (debug != null) {
 423                         debug.println("Constraints: failed algorithm " +
 424                                 "parameters constraint check " + aps);
 425                     }
 426 
 427                     return false;
 428                 }
 429             }
 430 
 431             return true;
 432         }
 433 
 434         // Check if constraints permit this cert.
 435         public void permits(String algorithm, ConstraintsParameters cp)
 436                 throws CertPathValidatorException {
 437             X509Certificate cert = cp.getCertificate();
 438 
 439             if (debug != null) {
 440                 debug.println("Constraints.permits(): " + cp.toString());

 441             }
 442 
 443             // Get all signature algorithms to check for constraints
 444             Set<String> algorithms = new HashSet<>();
 445             if (algorithm != null) {
 446                 algorithms.addAll(AlgorithmDecomposer.decomposeOneHash(algorithm));
 447                 algorithms.add(algorithm);
 448             }
 449 
 450             // Attempt to add the public key algorithm if cert provided
 451             if (cert != null) {
 452                 algorithms.add(cert.getPublicKey().getAlgorithm());
 453             }
 454             if (cp.getKey() != null) {
 455                 algorithms.add(cp.getKey().getAlgorithm());
 456             }
 457             // Check all applicable constraints
 458             for (String alg : algorithms) {
 459                 List<Constraint> list = getConstraints(alg);
 460                 if (list == null) {
 461                     continue;
 462                 }
 463                 for (Constraint constraint : list) {
 464                     constraint.permits(cp);
 465                 }
 466             }
 467         }
 468     }
 469 
 470     /**
 471      * This abstract Constraint class for algorithm-based checking
 472      * may contain one or more constraints.  If the '&' on the {@Security}
 473      * property is used, multiple constraints have been grouped together
 474      * requiring all the constraints to fail for the check to be disallowed.
 475      *


 574                 return true;
 575             }
 576             return false;
 577         }
 578 
 579         /**
 580          * Recursively check if this constraint is allowed,
 581          *
 582          * If {@code nextConstraint} is non-null, this method will
 583          * call {@code nextConstraint}'s {@code permit()} to check if the
 584          * constraint is allowed or denied.  If the constraint's
 585          * {@code permit()} is allowed, this method will exit this and any
 586          * recursive next() calls, returning 'true'.  If the constraints
 587          * called were disallowed the check will exit with 'false'.
 588          *
 589          * @param key Public key
 590          * @return 'true' if constraint allows the operation, 'false' if
 591          * the constraint denies the operation.
 592          */
 593         boolean next(Key key) {
 594             return nextConstraint != null && nextConstraint.permits(key);



 595         }
 596 
 597         String extendedMsg(ConstraintsParameters cp) {
 598             return (cp.getCertificate() == null ? "." :
 599                     " used with certificate: " +
 600                             cp.getCertificate().getSubjectX500Principal() +
 601                     (cp.getVariant() != Validator.VAR_GENERIC ?
 602                             ".  Usage was " + cp.getVariant() : "."));
 603         }
 604     }
 605 
 606     /*
 607      * This class contains constraints dealing with the certificate chain
 608      * of the certificate.
 609      */
 610     private static class jdkCAConstraint extends Constraint {
 611         jdkCAConstraint(String algo) {
 612             algorithm = algo;
 613         }
 614 


 826                     this.maxSize = length > 1 ? (length - 1) : 0;
 827                     break;
 828                 default:
 829                     // unlikely to happen
 830                     this.minSize = Integer.MAX_VALUE;
 831                     this.maxSize = -1;
 832             }
 833         }
 834 
 835         /*
 836          * If we are passed a certificate, extract the public key and use it.
 837          *
 838          * Check if each constraint fails and check if there is a linked
 839          * constraint  Any permitted constraint will exit the linked list
 840          * to allow the operation.
 841          */
 842         @Override
 843         public void permits(ConstraintsParameters cp)
 844                 throws CertPathValidatorException {
 845             Key key = null;
 846             if (cp.getKey() != null) {
 847                 key = cp.getKey();
 848             } else if (cp.getCertificate() != null) {
 849                 key = cp.getCertificate().getPublicKey();
 850             }
 851             if (key != null && !permitsImpl(key)) {
 852                 if (nextConstraint != null) {
 853                     nextConstraint.permits(cp);
 854                     return;
 855                 }
 856                 throw new CertPathValidatorException(
 857                         "Algorithm constraints check failed on keysize limits. " +
 858                         algorithm + " " + KeyUtil.getKeySize(key) + "bit key" +
 859                         extendedMsg(cp),
 860                         null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
 861             }
 862         }
 863 
 864 
 865         // Check if key constraint disable the specified key
 866         // Uses old style permit()
 867         @Override


< prev index next >