1 /* 2 * Copyright (c) 2010, 2015, 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 23 * questions. 24 */ 25 26 package sun.security.util; 27 28 import java.security.CryptoPrimitive; 29 import java.security.AlgorithmParameters; 30 import java.security.Key; 31 import java.util.Locale; 32 import java.util.Set; 33 import java.util.Collections; 34 import java.util.HashSet; 35 import java.util.Map; 36 import java.util.HashMap; 37 import java.util.regex.Pattern; 38 import java.util.regex.Matcher; 39 40 /** 41 * Algorithm constraints for disabled algorithms property 42 * 43 * See the "jdk.certpath.disabledAlgorithms" specification in java.security 44 * for the syntax of the disabled algorithm string. 45 */ 46 public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { 47 48 // the known security property, jdk.certpath.disabledAlgorithms 49 public static final String PROPERTY_CERTPATH_DISABLED_ALGS = 50 "jdk.certpath.disabledAlgorithms"; 51 52 // the known security property, jdk.tls.disabledAlgorithms 53 public static final String PROPERTY_TLS_DISABLED_ALGS = 54 "jdk.tls.disabledAlgorithms"; 55 56 private static final Map<String, String[]> disabledAlgorithmsMap = 57 new HashMap<>(); 58 private static final Map<String, KeySizeConstraints> keySizeConstraintsMap = 59 new HashMap<>(); 60 61 private final String[] disabledAlgorithms; 62 private final KeySizeConstraints keySizeConstraints; 63 64 /** 65 * Initialize algorithm constraints with the specified security property. 66 * 67 * @param propertyName the security property name that define the disabled 68 * algorithm constraints 69 */ 70 public DisabledAlgorithmConstraints(String propertyName) { 71 this(propertyName, new AlgorithmDecomposer()); 72 } 73 74 public DisabledAlgorithmConstraints(String propertyName, 75 AlgorithmDecomposer decomposer) { 76 super(decomposer); 77 disabledAlgorithms = getAlgorithms(disabledAlgorithmsMap, propertyName); 78 keySizeConstraints = getKeySizeConstraints(disabledAlgorithms, 79 propertyName); 80 } 81 82 @Override 83 public final boolean permits(Set<CryptoPrimitive> primitives, 84 String algorithm, AlgorithmParameters parameters) { 85 86 if (primitives == null || primitives.isEmpty()) { 87 throw new IllegalArgumentException( 88 "No cryptographic primitive specified"); 89 } 90 91 return checkAlgorithm(disabledAlgorithms, algorithm, decomposer); 92 } 93 94 @Override 95 public final boolean permits(Set<CryptoPrimitive> primitives, Key key) { 96 return checkConstraints(primitives, "", key, null); 97 } 98 99 @Override 100 public final boolean permits(Set<CryptoPrimitive> primitives, 101 String algorithm, Key key, AlgorithmParameters parameters) { 102 103 if (algorithm == null || algorithm.length() == 0) { 104 throw new IllegalArgumentException("No algorithm name specified"); 105 } 106 107 return checkConstraints(primitives, algorithm, key, parameters); 108 } 109 110 // Check algorithm constraints 111 private boolean checkConstraints(Set<CryptoPrimitive> primitives, 112 String algorithm, Key key, AlgorithmParameters parameters) { 113 114 // check the key parameter, it cannot be null. 115 if (key == null) { 116 throw new IllegalArgumentException("The key cannot be null"); 117 } 118 119 // check the target algorithm 120 if (algorithm != null && algorithm.length() != 0) { 121 if (!permits(primitives, algorithm, parameters)) { 122 return false; 123 } 124 } 125 126 // check the key algorithm 127 if (!permits(primitives, key.getAlgorithm(), null)) { 128 return false; 129 } 130 131 // check the key constraints 132 if (keySizeConstraints.disables(key)) { 133 return false; 134 } 135 136 return true; 137 } 138 139 private static KeySizeConstraints getKeySizeConstraints( 140 String[] disabledAlgorithms, String propertyName) { 141 synchronized (keySizeConstraintsMap) { 142 if(!keySizeConstraintsMap.containsKey(propertyName)) { 143 // map the key constraints 144 KeySizeConstraints keySizeConstraints = 145 new KeySizeConstraints(disabledAlgorithms); 146 keySizeConstraintsMap.put(propertyName, keySizeConstraints); 147 } 148 149 return keySizeConstraintsMap.get(propertyName); 150 } 151 } 152 153 /** 154 * key constraints 155 */ 156 private static class KeySizeConstraints { 157 private static final Pattern pattern = Pattern.compile( 158 "(\\S+)\\s+keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)"); 159 160 private Map<String, Set<KeySizeConstraint>> constraintsMap = 161 Collections.synchronizedMap( 162 new HashMap<String, Set<KeySizeConstraint>>()); 163 164 public KeySizeConstraints(String[] restrictions) { 165 for (String restriction : restrictions) { 166 if (restriction == null || restriction.isEmpty()) { 167 continue; 168 } 169 170 Matcher matcher = pattern.matcher(restriction); 171 if (matcher.matches()) { 172 String algorithm = matcher.group(1); 173 174 KeySizeConstraint.Operator operator = 175 KeySizeConstraint.Operator.of(matcher.group(2)); 176 int length = Integer.parseInt(matcher.group(3)); 177 178 algorithm = algorithm.toLowerCase(Locale.ENGLISH); 179 180 synchronized (constraintsMap) { 181 if (!constraintsMap.containsKey(algorithm)) { 182 constraintsMap.put(algorithm, 183 new HashSet<KeySizeConstraint>()); 184 } 185 186 Set<KeySizeConstraint> constraintSet = 187 constraintsMap.get(algorithm); 188 KeySizeConstraint constraint = 189 new KeySizeConstraint(operator, length); 190 constraintSet.add(constraint); 191 } 192 } 193 } 194 } 195 196 // Does this KeySizeConstraints disable the specified key? 197 public boolean disables(Key key) { 198 String algorithm = key.getAlgorithm().toLowerCase(Locale.ENGLISH); 199 synchronized (constraintsMap) { 200 if (constraintsMap.containsKey(algorithm)) { 201 Set<KeySizeConstraint> constraintSet = 202 constraintsMap.get(algorithm); 203 for (KeySizeConstraint constraint : constraintSet) { 204 if (constraint.disables(key)) { 205 return true; 206 } 207 } 208 } 209 } 210 211 return false; 212 } 213 } 214 215 /** 216 * Key size constraint. 217 * 218 * e.g. "keysize <= 1024" 219 */ 220 private static class KeySizeConstraint { 221 // operator 222 static enum Operator { 223 EQ, // "==" 224 NE, // "!=" 225 LT, // "<" 226 LE, // "<=" 227 GT, // ">" 228 GE; // ">=" 229 230 static Operator of(String s) { 231 switch (s) { 232 case "==": 233 return EQ; 234 case "!=": 235 return NE; 236 case "<": 237 return LT; 238 case "<=": 239 return LE; 240 case ">": 241 return GT; 242 case ">=": 243 return GE; 244 } 245 246 throw new IllegalArgumentException( 247 s + " is not a legal Operator"); 248 } 249 } 250 251 private int minSize; // the minimal available key size 252 private int maxSize; // the maximal available key size 253 private int prohibitedSize = -1; // unavailable key sizes 254 255 public KeySizeConstraint(Operator operator, int length) { 256 switch (operator) { 257 case EQ: // an unavailable key size 258 this.minSize = 0; 259 this.maxSize = Integer.MAX_VALUE; 260 prohibitedSize = length; 261 break; 262 case NE: 263 this.minSize = length; 264 this.maxSize = length; 265 break; 266 case LT: 267 this.minSize = length; 268 this.maxSize = Integer.MAX_VALUE; 269 break; 270 case LE: 271 this.minSize = length + 1; 272 this.maxSize = Integer.MAX_VALUE; 273 break; 274 case GT: 275 this.minSize = 0; 276 this.maxSize = length; 277 break; 278 case GE: 279 this.minSize = 0; 280 this.maxSize = length > 1 ? (length - 1) : 0; 281 break; 282 default: 283 // unlikely to happen 284 this.minSize = Integer.MAX_VALUE; 285 this.maxSize = -1; 286 } 287 } 288 289 // Does this key constraint disable the specified key? 290 public boolean disables(Key key) { 291 int size = KeyUtil.getKeySize(key); 292 293 if (size == 0) { 294 return true; // we don't allow any key of size 0. 295 } else if (size > 0) { 296 return ((size < minSize) || (size > maxSize) || 297 (prohibitedSize == size)); 298 } // Otherwise, the key size is not accessible. Conservatively, 299 // please don't disable such keys. 300 301 return false; 302 } 303 } 304 305 } 306 | 1 /* 2 * Copyright (c) 2010, 2016, 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 23 * questions. 24 */ 25 26 package sun.security.util; 27 28 import java.security.CryptoPrimitive; 29 import java.security.AlgorithmParameters; 30 import java.security.Key; 31 import java.security.cert.CertPathValidatorException; 32 import java.security.cert.CertPathValidatorException.BasicReason; 33 import java.security.cert.X509Certificate; 34 import java.util.HashMap; 35 import java.util.HashSet; 36 import java.util.Locale; 37 import java.util.Map; 38 import java.util.Set; 39 import java.util.regex.Pattern; 40 import java.util.regex.Matcher; 41 42 /** 43 * Algorithm constraints for disabled algorithms property 44 * 45 * See the "jdk.certpath.disabledAlgorithms" specification in java.security 46 * for the syntax of the disabled algorithm string. 47 */ 48 public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { 49 private static final Debug debug = Debug.getInstance("certpath"); 50 51 // the known security property, jdk.certpath.disabledAlgorithms 52 public static final String PROPERTY_CERTPATH_DISABLED_ALGS = 53 "jdk.certpath.disabledAlgorithms"; 54 55 // the known security property, jdk.tls.disabledAlgorithms 56 public static final String PROPERTY_TLS_DISABLED_ALGS = 57 "jdk.tls.disabledAlgorithms"; 58 59 private final String[] disabledAlgorithms; 60 private final Constraints algorithmConstraints; 61 62 /** 63 * Initialize algorithm constraints with the specified security property. 64 * 65 * @param propertyName the security property name that define the disabled 66 * algorithm constraints 67 */ 68 public DisabledAlgorithmConstraints(String propertyName) { 69 this(propertyName, new AlgorithmDecomposer()); 70 } 71 72 public DisabledAlgorithmConstraints(String propertyName, 73 AlgorithmDecomposer decomposer) { 74 super(decomposer); 75 disabledAlgorithms = getAlgorithms(propertyName); 76 algorithmConstraints = new Constraints(disabledAlgorithms); 77 } 78 79 /* 80 * This only checks if the algorithm has been completely disabled. If 81 * there are keysize or other limit, this method allow the algorithm. 82 */ 83 @Override 84 public final boolean permits(Set<CryptoPrimitive> primitives, 85 String algorithm, AlgorithmParameters parameters) { 86 87 if (primitives == null || primitives.isEmpty()) { 88 throw new IllegalArgumentException( 89 "No cryptographic primitive specified"); 90 } 91 92 return checkAlgorithm(disabledAlgorithms, algorithm, decomposer); 93 } 94 95 /* 96 * Checks if the key algorithm has been disabled or constraints have been 97 * placed on the key. 98 */ 99 @Override 100 public final boolean permits(Set<CryptoPrimitive> primitives, Key key) { 101 return checkConstraints(primitives, "", key, null); 102 } 103 104 /* 105 * Checks if the key algorithm has been disabled or if constraints have 106 * been placed on the key. 107 */ 108 @Override 109 public final boolean permits(Set<CryptoPrimitive> primitives, 110 String algorithm, Key key, AlgorithmParameters parameters) { 111 112 if (algorithm == null || algorithm.length() == 0) { 113 throw new IllegalArgumentException("No algorithm name specified"); 114 } 115 116 return checkConstraints(primitives, algorithm, key, parameters); 117 } 118 119 /* 120 * Check if a x509Certificate object is permitted. Check if all 121 * algorithms are allowed, certificate constraints, and the 122 * public key against key constraints. 123 * 124 * Uses new style permit() which throws exceptions. 125 */ 126 public final void permits(Set<CryptoPrimitive> primitives, 127 CertConstraintParameters cp) throws CertPathValidatorException { 128 checkConstraints(primitives, cp); 129 } 130 131 /* 132 * Check if Certificate object is within the constraints. 133 * Uses new style permit() which throws exceptions. 134 */ 135 public final void permits(Set<CryptoPrimitive> primitives, 136 X509Certificate cert) throws CertPathValidatorException { 137 checkConstraints(primitives, new CertConstraintParameters(cert)); 138 } 139 140 // Check if a string is contained inside the property 141 public boolean checkProperty(String param) { 142 param = param.toLowerCase(Locale.ENGLISH); 143 for (String block : disabledAlgorithms) { 144 if (block.toLowerCase(Locale.ENGLISH).indexOf(param) >= 0) { 145 return true; 146 } 147 } 148 return false; 149 } 150 151 // Check algorithm constraints with key and algorithm 152 private boolean checkConstraints(Set<CryptoPrimitive> primitives, 153 String algorithm, Key key, AlgorithmParameters parameters) { 154 155 // check the key parameter, it cannot be null. 156 if (key == null) { 157 throw new IllegalArgumentException("The key cannot be null"); 158 } 159 160 // check the signature algorithm 161 if (algorithm != null && algorithm.length() != 0) { 162 if (!permits(primitives, algorithm, parameters)) { 163 return false; 164 } 165 } 166 167 // check the key algorithm 168 if (!permits(primitives, key.getAlgorithm(), null)) { 169 return false; 170 } 171 172 // check the key constraints 173 return algorithmConstraints.permits(key); 174 } 175 176 /* 177 * Check algorithm constraints with Certificate 178 * Uses new style permit() which throws exceptions. 179 */ 180 private void checkConstraints(Set<CryptoPrimitive> primitives, 181 CertConstraintParameters cp) throws CertPathValidatorException { 182 183 X509Certificate cert = cp.getCertificate(); 184 String algorithm = cert.getSigAlgName(); 185 186 // Check signature algorithm is not disabled 187 if (!permits(primitives, algorithm, null)) { 188 throw new CertPathValidatorException( 189 "Algorithm constraints check failed on disabled "+ 190 "signature algorithm: " + algorithm, 191 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); 192 } 193 194 // Check key algorithm is not disabled 195 if (!permits(primitives, cert.getPublicKey().getAlgorithm(), null)) { 196 throw new CertPathValidatorException( 197 "Algorithm constraints check failed on disabled "+ 198 "public key algorithm: " + algorithm, 199 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); 200 } 201 202 // Check the certificate and key constraints 203 algorithmConstraints.permits(cp); 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 CertConstraintParameters 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, Set<Constraint>> constraintsMap = new HashMap<>(); 227 private static final Pattern keySizePattern = Pattern.compile( 228 "keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)"); 229 230 public Constraints(String[] constraintArray) { 231 for (String constraintEntry : constraintArray) { 232 if (constraintEntry == null || constraintEntry.isEmpty()) { 233 continue; 234 } 235 constraintEntry = constraintEntry.trim(); 236 if (debug != null) { 237 debug.println("Constraints: " + constraintEntry); 238 } 239 240 // Check if constraint is a complete disabling of an 241 // algorithm or has conditions. 242 String algorithm; 243 String policy; 244 int space = constraintEntry.indexOf(' '); 245 if (space > 0) { 246 algorithm = AlgorithmDecomposer.hashName( 247 constraintEntry.substring(0, space). 248 toUpperCase(Locale.ENGLISH)); 249 policy = constraintEntry.substring(space + 1); 250 } else { 251 constraintsMap.computeIfAbsent( 252 constraintEntry.toUpperCase(Locale.ENGLISH), 253 k -> new HashSet<>()); 254 continue; 255 } 256 257 // Convert constraint conditions into Constraint classes 258 Constraint c, lastConstraint = null; 259 for (String entry : policy.split("&")) { 260 entry = entry.trim(); 261 262 Matcher matcher = keySizePattern.matcher(entry); 263 if (matcher.matches()) { 264 if (debug != null) { 265 debug.println("Constraints set to keySize: " + 266 entry); 267 } 268 c = new KeySizeConstraint(algorithm, 269 KeySizeConstraint.Operator.of(matcher.group(1)), 270 Integer.parseInt(matcher.group(2))); 271 } else if (entry.equalsIgnoreCase("jdkCA")) { 272 if (debug != null) { 273 debug.println("Constraints set to Cert: " + entry); 274 } 275 c = new CertConstraint(algorithm); 276 } else { 277 throw new IllegalArgumentException("Error in security" + 278 " property. Constraint unknown: " + entry); 279 } 280 281 // Link multiple conditions for a single constraint 282 // into a linked list. 283 if (lastConstraint == null) { 284 if (!constraintsMap.containsKey(algorithm)) { 285 constraintsMap.putIfAbsent(algorithm, 286 new HashSet<>()); 287 } 288 constraintsMap.get(algorithm).add(c); 289 } else { 290 lastConstraint.nextConstraint = c; 291 } 292 lastConstraint = c; 293 } 294 } 295 } 296 297 // Get applicable constraints based off the signature algorithm 298 private Set<Constraint> getConstraints(String algorithm) { 299 return constraintsMap.get(algorithm); 300 } 301 302 // Check if KeySizeConstraints permit the specified key 303 public boolean permits(Key key) { 304 Set<Constraint> set = getConstraints(key.getAlgorithm()); 305 if (set == null) { 306 return true; 307 } 308 for (Constraint constraint : set) { 309 if (!constraint.permits(key)) { 310 if (debug != null) { 311 debug.println("keySizeConstraint: failed key " + 312 "constraint check " + KeyUtil.getKeySize(key)); 313 } 314 return false; 315 } 316 } 317 return true; 318 } 319 320 // Check if constraints permit this cert. 321 public void permits(CertConstraintParameters cp) 322 throws CertPathValidatorException { 323 X509Certificate cert = cp.getCertificate(); 324 325 if (debug != null) { 326 debug.println("Constraints.permits(): " + cert.getSigAlgName()); 327 } 328 329 // Get all signature algorithms to check for constraints 330 Set<String> algorithms = 331 AlgorithmDecomposer.decomposeOneHash(cert.getSigAlgName()); 332 if (algorithms == null || algorithms.isEmpty()) { 333 return; 334 } 335 336 // Attempt to add the public key algorithm to the set 337 algorithms.add(cert.getPublicKey().getAlgorithm()); 338 339 // Check all applicable constraints 340 for (String algorithm : algorithms) { 341 Set<Constraint> set = getConstraints(algorithm); 342 if (set == null) { 343 continue; 344 } 345 for (Constraint constraint : set) { 346 constraint.permits(cp); 347 } 348 } 349 } 350 } 351 352 // Abstract class for algorithm constraint checking 353 private abstract static class Constraint { 354 String algorithm; 355 Constraint nextConstraint = null; 356 357 // operator 358 enum Operator { 359 EQ, // "==" 360 NE, // "!=" 361 LT, // "<" 362 LE, // "<=" 363 GT, // ">" 364 GE; // ">=" 365 366 static Operator of(String s) { 367 switch (s) { 368 case "==": 369 return EQ; 370 case "!=": 371 return NE; 372 case "<": 373 return LT; 374 case "<=": 375 return LE; 376 case ">": 377 return GT; 378 case ">=": 379 return GE; 380 } 381 382 throw new IllegalArgumentException("Error in security " + 383 "property. " + s + " is not a legal Operator"); 384 } 385 } 386 387 /** 388 * Check if an algorithm constraint permit this key to be used. 389 * @param key Public key 390 * @return true if constraints do not match 391 */ 392 public boolean permits(Key key) { 393 return true; 394 } 395 396 /** 397 * Check if an algorithm constraint is permit this certificate to 398 * be used. 399 * @param cp CertificateParameter containing certificate and state info 400 * @return true if constraints do not match 401 */ 402 public abstract void permits(CertConstraintParameters cp) 403 throws CertPathValidatorException; 404 } 405 406 /* 407 * This class contains constraints dealing with the certificate chain 408 * of the certificate. 409 */ 410 private static class CertConstraint extends Constraint { 411 412 CertConstraint(String algo) { 413 algorithm = algo; 414 } 415 416 /* 417 * Check if each constraint fails and check if there is a linked 418 * constraint Any permitted constraint will exit the linked list 419 * to allow the operation. 420 */ 421 public void permits(CertConstraintParameters cp) 422 throws CertPathValidatorException { 423 if (debug != null) { 424 debug.println("CertConstraints.permits(): " + algorithm); 425 } 426 427 // Return false if the chain has a cacerts trust anchor. 428 if (cp.isTrustedMatch()) { 429 if (nextConstraint != null) { 430 nextConstraint.permits(cp); 431 return; 432 } 433 throw new CertPathValidatorException( 434 "Algorithm constraints check failed on certificate " + 435 "anchor limits", 436 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); 437 } 438 } 439 } 440 441 442 /* 443 * This class contains constraints dealing with the key size 444 * support limits per algorithm. e.g. "keySize <= 1024" 445 */ 446 private static class KeySizeConstraint extends Constraint { 447 448 private int minSize; // the minimal available key size 449 private int maxSize; // the maximal available key size 450 private int prohibitedSize = -1; // unavailable key sizes 451 452 public KeySizeConstraint(String algo, Operator operator, int length) { 453 algorithm = algo; 454 switch (operator) { 455 case EQ: // an unavailable key size 456 this.minSize = 0; 457 this.maxSize = Integer.MAX_VALUE; 458 prohibitedSize = length; 459 break; 460 case NE: 461 this.minSize = length; 462 this.maxSize = length; 463 break; 464 case LT: 465 this.minSize = length; 466 this.maxSize = Integer.MAX_VALUE; 467 break; 468 case LE: 469 this.minSize = length + 1; 470 this.maxSize = Integer.MAX_VALUE; 471 break; 472 case GT: 473 this.minSize = 0; 474 this.maxSize = length; 475 break; 476 case GE: 477 this.minSize = 0; 478 this.maxSize = length > 1 ? (length - 1) : 0; 479 break; 480 default: 481 // unlikely to happen 482 this.minSize = Integer.MAX_VALUE; 483 this.maxSize = -1; 484 } 485 } 486 487 /* 488 * If we are passed a certificate, extract the public key and use it. 489 * 490 * Check if each constraint fails and check if there is a linked 491 * constraint Any permitted constraint will exit the linked list 492 * to allow the operation. 493 */ 494 public void permits(CertConstraintParameters cp) 495 throws CertPathValidatorException { 496 if (!permitsImpl(cp.getCertificate().getPublicKey())) { 497 if (nextConstraint != null) { 498 nextConstraint.permits(cp); 499 return; 500 } 501 throw new CertPathValidatorException( 502 "Algorithm constraints check failed on keysize limits", 503 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); 504 } 505 } 506 507 508 // Check if key constraint disable the specified key 509 // Uses old style permit() 510 public boolean permits(Key key) { 511 // If we recursively find a constraint that permits us to use 512 // this key, return true and skip any other constraint checks. 513 if (nextConstraint != null && nextConstraint.permits(key)) { 514 return true; 515 } 516 if (debug != null) { 517 debug.println("KeySizeConstraints.permits(): " + algorithm); 518 } 519 520 return permitsImpl(key); 521 } 522 523 private boolean permitsImpl(Key key) { 524 // Verify this constraint is for this public key algorithm 525 if (algorithm.compareToIgnoreCase(key.getAlgorithm()) != 0) { 526 return true; 527 } 528 529 int size = KeyUtil.getKeySize(key); 530 if (size == 0) { 531 return false; // we don't allow any key of size 0. 532 } else if (size > 0) { 533 return !((size < minSize) || (size > maxSize) || 534 (prohibitedSize == size)); 535 } // Otherwise, the key size is not accessible. Conservatively, 536 // please don't disable such keys. 537 538 return true; 539 } 540 } 541 } 542 |