提交 25f17276 编写于 作者: I igerasim

8178728: Check the AlgorithmParameters in algorithm constraints

Reviewed-by: valeriep, ascarpino
上级 fd93e68f
/* /*
* 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. * 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
...@@ -27,6 +27,8 @@ package sun.security.util; ...@@ -27,6 +27,8 @@ package sun.security.util;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.Arrays;
import java.util.Collection;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/** /**
...@@ -133,6 +135,23 @@ public class AlgorithmDecomposer { ...@@ -133,6 +135,23 @@ public class AlgorithmDecomposer {
return elements; 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) { private static void hasLoop(Set<String> elements, String find, String replace) {
if (elements.contains(find)) { if (elements.contains(find)) {
if (!elements.contains(replace)) { if (!elements.contains(replace)) {
......
...@@ -45,6 +45,7 @@ import java.util.List; ...@@ -45,6 +45,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Collection;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.regex.Pattern; import java.util.regex.Pattern;
...@@ -106,7 +107,15 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -106,7 +107,15 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
@Override @Override
public final boolean permits(Set<CryptoPrimitive> primitives, public final boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, AlgorithmParameters parameters) { 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;
} }
/* /*
...@@ -242,7 +251,12 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -242,7 +251,12 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
List<Constraint> constraintList = List<Constraint> constraintList =
constraintsMap.getOrDefault(algorithm, constraintsMap.getOrDefault(algorithm,
new ArrayList<>(1)); new ArrayList<>(1));
constraintsMap.putIfAbsent(algorithm, constraintList);
// Consider the impact of algorithm aliases.
for (String alias : AlgorithmDecomposer.getAliases(algorithm)) {
constraintsMap.putIfAbsent(alias, constraintList);
}
if (space <= 0) { if (space <= 0) {
constraintList.add(new DisabledConstraint(algorithm)); constraintList.add(new DisabledConstraint(algorithm));
continue; continue;
...@@ -351,6 +365,27 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -351,6 +365,27 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
return true; 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. // Check if constraints permit this cert.
public void permits(String algorithm, ConstraintsParameters cp) public void permits(String algorithm, ConstraintsParameters cp)
throws CertPathValidatorException { throws CertPathValidatorException {
...@@ -444,6 +479,18 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -444,6 +479,18 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
return true; return true;
} }
/**
* 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 * Check if an algorithm constraint is permitted with a given
* ConstraintsParameters. * ConstraintsParameters.
...@@ -528,6 +575,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -528,6 +575,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
* call next() for any following constraints. If it does not, exit * call next() for any following constraints. If it does not, exit
* as this constraint(s) does not restrict the operation. * as this constraint(s) does not restrict the operation.
*/ */
@Override
public void permits(ConstraintsParameters cp) public void permits(ConstraintsParameters cp)
throws CertPathValidatorException { throws CertPathValidatorException {
if (debug != null) { if (debug != null) {
...@@ -551,100 +599,101 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -551,100 +599,101 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
* This class handles the denyAfter constraint. The date is in the UTC/GMT * This class handles the denyAfter constraint. The date is in the UTC/GMT
* timezone. * timezone.
*/ */
private static class DenyAfterConstraint extends Constraint { private static class DenyAfterConstraint extends Constraint {
private Date denyAfterDate; private Date denyAfterDate;
private static final SimpleDateFormat dateFormat = private static final SimpleDateFormat dateFormat =
new SimpleDateFormat("EEE, MMM d HH:mm:ss z yyyy"); new SimpleDateFormat("EEE, MMM d HH:mm:ss z yyyy");
DenyAfterConstraint(String algo, int year, int month, int day) { DenyAfterConstraint(String algo, int year, int month, int day) {
Calendar c; Calendar c;
algorithm = algo; algorithm = algo;
if (debug != null) { if (debug != null) {
debug.println("DenyAfterConstraint read in as: year " + debug.println("DenyAfterConstraint read in as: year " +
year + ", month = " + month + ", day = " + day); year + ", month = " + month + ", day = " + day);
} }
c = new Calendar.Builder().setTimeZone(TimeZone.getTimeZone("GMT")) c = new Calendar.Builder().setTimeZone(TimeZone.getTimeZone("GMT"))
.setDate(year, month - 1, day).build(); .setDate(year, month - 1, day).build();
if (year > c.getActualMaximum(Calendar.YEAR) || if (year > c.getActualMaximum(Calendar.YEAR) ||
year < c.getActualMinimum(Calendar.YEAR)) { year < c.getActualMinimum(Calendar.YEAR)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Invalid year given in constraint: " + year); "Invalid year given in constraint: " + year);
} }
if ((month - 1) > c.getActualMaximum(Calendar.MONTH) || if ((month - 1) > c.getActualMaximum(Calendar.MONTH) ||
(month - 1) < c.getActualMinimum(Calendar.MONTH)) { (month - 1) < c.getActualMinimum(Calendar.MONTH)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Invalid month given in constraint: " + month); "Invalid month given in constraint: " + month);
} }
if (day > c.getActualMaximum(Calendar.DAY_OF_MONTH) || if (day > c.getActualMaximum(Calendar.DAY_OF_MONTH) ||
day < c.getActualMinimum(Calendar.DAY_OF_MONTH)) { day < c.getActualMinimum(Calendar.DAY_OF_MONTH)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Invalid Day of Month given in constraint: " + day); "Invalid Day of Month given in constraint: " + day);
} }
denyAfterDate = c.getTime(); denyAfterDate = c.getTime();
if (debug != null) { if (debug != null) {
debug.println("DenyAfterConstraint date set to: " + debug.println("DenyAfterConstraint date set to: " +
dateFormat.format(denyAfterDate)); dateFormat.format(denyAfterDate));
} }
} }
/* /*
* Checking that the provided date is not beyond the constraint date. * Checking that the provided date is not beyond the constraint date.
* The provided date can be the PKIXParameter date if given, * The provided date can be the PKIXParameter date if given,
* otherwise it is the current date. * otherwise it is the current date.
* *
* If the constraint disallows, call next() for any following * If the constraint disallows, call next() for any following
* constraints. Throw an exception if this is the last constraint. * constraints. Throw an exception if this is the last constraint.
*/ */
@Override @Override
public void permits(ConstraintsParameters cp) public void permits(ConstraintsParameters cp)
throws CertPathValidatorException { throws CertPathValidatorException {
Date currentDate; Date currentDate;
String errmsg; String errmsg;
if (cp.getJARTimestamp() != null) { if (cp.getJARTimestamp() != null) {
currentDate = cp.getJARTimestamp().getTimestamp(); currentDate = cp.getJARTimestamp().getTimestamp();
errmsg = "JAR Timestamp date: "; errmsg = "JAR Timestamp date: ";
} else if (cp.getPKIXParamDate() != null) { } else if (cp.getPKIXParamDate() != null) {
currentDate = cp.getPKIXParamDate(); currentDate = cp.getPKIXParamDate();
errmsg = "PKIXParameter date: "; errmsg = "PKIXParameter date: ";
} else { } else {
currentDate = new Date(); currentDate = new Date();
errmsg = "Current date: "; errmsg = "Current date: ";
} }
if (!denyAfterDate.after(currentDate)) { if (!denyAfterDate.after(currentDate)) {
if (next(cp)) { if (next(cp)) {
return; return;
} }
throw new CertPathValidatorException( throw new CertPathValidatorException(
"denyAfter constraint check failed: " + algorithm + "denyAfter constraint check failed: " + algorithm +
" used with Constraint date: " + " used with Constraint date: " +
dateFormat.format(denyAfterDate) + "; " + errmsg + dateFormat.format(denyAfterDate) + "; " + errmsg +
dateFormat.format(currentDate) + extendedMsg(cp), dateFormat.format(currentDate) + extendedMsg(cp),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
} }
} }
/* /*
* Return result if the constraint's date is beyond the current date * Return result if the constraint's date is beyond the current date
* in UTC timezone. * in UTC timezone.
*/ */
public boolean permits(Key key) { @Override
if (next(key)) { public boolean permits(Key key) {
return true; if (next(key)) {
} return true;
if (debug != null) { }
debug.println("DenyAfterConstraints.permits(): " + algorithm); if (debug != null) {
} debug.println("DenyAfterConstraints.permits(): " + algorithm);
}
return denyAfterDate.after(new Date());
} return denyAfterDate.after(new Date());
} }
}
/* /*
* The usage constraint is for the "usage" keyword. It checks against the * The usage constraint is for the "usage" keyword. It checks against the
...@@ -658,6 +707,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -658,6 +707,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
this.usages = usages; this.usages = usages;
} }
@Override
public void permits(ConstraintsParameters cp) public void permits(ConstraintsParameters cp)
throws CertPathValidatorException { throws CertPathValidatorException {
for (String usage : usages) { for (String usage : usages) {
...@@ -746,6 +796,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -746,6 +796,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
* constraint Any permitted constraint will exit the linked list * constraint Any permitted constraint will exit the linked list
* to allow the operation. * to allow the operation.
*/ */
@Override
public void permits(ConstraintsParameters cp) public void permits(ConstraintsParameters cp)
throws CertPathValidatorException { throws CertPathValidatorException {
Key key = null; Key key = null;
...@@ -770,6 +821,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -770,6 +821,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
// Check if key constraint disable the specified key // Check if key constraint disable the specified key
// Uses old style permit() // Uses old style permit()
@Override
public boolean permits(Key key) { public boolean permits(Key key) {
// If we recursively find a constraint that permits us to use // If we recursively find a constraint that permits us to use
// this key, return true and skip any other constraint checks. // this key, return true and skip any other constraint checks.
...@@ -783,6 +835,30 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -783,6 +835,30 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
return permitsImpl(key); 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) { private boolean permitsImpl(Key key) {
// Verify this constraint is for this public key algorithm // Verify this constraint is for this public key algorithm
if (algorithm.compareToIgnoreCase(key.getAlgorithm()) != 0) { if (algorithm.compareToIgnoreCase(key.getAlgorithm()) != 0) {
...@@ -810,6 +886,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -810,6 +886,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
algorithm = algo; algorithm = algo;
} }
@Override
public void permits(ConstraintsParameters cp) public void permits(ConstraintsParameters cp)
throws CertPathValidatorException { throws CertPathValidatorException {
throw new CertPathValidatorException( throw new CertPathValidatorException(
...@@ -818,6 +895,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { ...@@ -818,6 +895,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
} }
@Override
public boolean permits(Key key) { public boolean permits(Key key) {
return false; return false;
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
package sun.security.util; package sun.security.util;
import java.security.AlgorithmParameters;
import java.security.Key; import java.security.Key;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.security.AccessController; import java.security.AccessController;
...@@ -35,6 +36,8 @@ import java.security.interfaces.DSAKey; ...@@ -35,6 +36,8 @@ import java.security.interfaces.DSAKey;
import java.security.interfaces.DSAParams; import java.security.interfaces.DSAParams;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.spec.KeySpec; import java.security.spec.KeySpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHKey; import javax.crypto.interfaces.DHKey;
import javax.crypto.interfaces.DHPublicKey; import javax.crypto.interfaces.DHPublicKey;
...@@ -99,6 +102,61 @@ public final class KeyUtil { ...@@ -99,6 +102,61 @@ public final class KeyUtil {
return size; return size;
} }
/**
* 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();
switch (algorithm) {
case "EC":
try {
ECKeySizeParameterSpec ps = parameters.getParameterSpec(
ECKeySizeParameterSpec.class);
if (ps != null) {
return ps.getKeySize();
}
} catch (InvalidParameterSpecException ipse) {
// ignore
}
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).
break;
case "DiffieHellman":
try {
DHParameterSpec ps = parameters.getParameterSpec(
DHParameterSpec.class);
if (ps != null) {
return ps.getP().bitLength();
}
} catch (InvalidParameterSpecException ipse) {
// ignore
}
break;
// May support more AlgorithmParameters algorithms in the future.
}
return -1;
}
/** /**
* Returns whether the key is valid or not. * Returns whether the key is valid or not.
* <P> * <P>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册