RFR 8140422: Add mechanism to allow non default root CAs to be not subject to algorithm restrictions
Sean Mullan
sean.mullan at oracle.com
Tue Mar 8 21:55:27 UTC 2016
You should also copy build-dev on the next iteration since there are a
few Makefile changes.
On 02/29/2016 11:55 AM, Anthony Scarpino wrote:
> I need a code review of this change:
>
> http://cr.openjdk.java.net/~ascarpino/8140422/webrev/
>
> Currently CertPath algorithm restrictions allow or deny all
> certificates. This change adds the ability to reject certificate chains
> that contain a restricted algorithm and the chain terminates at a root
> CA; therefore, allowing a self-signed or chain that does not terminate
> at a root CA.
>
> https://bugs.openjdk.java.net/browse/JDK-8140422
Looks good, but had a few comments as I went through ...
java.security
-------------
551 # "cacerts" prohibits the algorithm only if it is used in a
552 # certificate chain that terminates at a distribution provided
553 # trust anchor in the lib/security/cacerts keystore. All other
554 # chains are not affected. Example: to apply this constraint
555 # to SHA-1 certificates, include the following: "SHA1 cacerts"
Suggest rewording in middle part: "... at a trust anchor in the
lib/security/cacerts.fingerprints file which is initially seeded with
the fingerprints of the certificates in the lib/security/cacerts keystore."
Also, add the following sentence: "If the cacerts constraint is not set,
then all chains using the specified algorithm are restricted."
563 # All DisabledAlgorithms are processed in the order defined in the
564 # property. This requires lower keysize constraints to be specified
565 # before larger keysize constraints of the same algorithm.
Is this still an issue? Constraints of the same algorithm are evaluated
as an AND, so the order should not matter (I think).
CACertsHasher
-------------
I think it would be useful to emit the subject DN of the certificate as
a comment (ex: "# CN=RootsRUs, ...") above each fingerprint, as it would
help associate the fingerprint with the root. Then, you can ignore
comments when you parse the file in AnchorCertificates.
AnchorCertificates
------------------
38 /**
39 * The purpose of this class is to determine if a trust anchor
certificate
40 * is one of the default trust anchors that comes pre-installed
with the JRE
41 * in the cacerts file. A locally installed trust anchor would not
be a default
42 * trust anchor
43 */
The determination is based off the cacerts.fingerprints file, so maybe a
better wording is: "The purpose of this class is to determine if a trust
anchor certificate is in the cacerts.fingerprints file which is
initially seeded with the fingerprints of the certificates in the
cacerts file. A trust anchor that is subsequently added to the cacerts
file but not the cacerts.fingerprints file would not be a match."
74 debug.println("Error parsing cacerts.md");
typo: cacerts.fingerprints
83 decomposer = new AlgorithmDecomposer();
Doesn't seem to be used, delete?
92 public static boolean isAnchor(X509Certificate cert) {
A better name for this method might be contains().
CertificateParameters
---------------------
37 public class CertificateParameters {
A better name might be CertConstraintParameters.
43 this(X509CertImpl.toImpl(c), anchor);
It doesn't seem like you need to convert this to an X509CertImpl. In
DisabledAlgorithmConstraints, you just call methods on X509Certificate.
46 public CertificateParameters(X509Certificate c) throws
CertificateException {
Doesn't seem to be used; remove?
50 public CertificateParameters(X509CertImpl c, boolean anchor) {
Make private, or just combine with other ctor as it really isn't needed.
59 public boolean isTrustedChain() {
A better name might be "isAnchoredToCaCert".
63 public X509CertImpl getCertificate() {
Change return type to X509Certificate.
AlgorithmChecker
----------------
93 // True if trust anchor checking finds a match in the cacerts file
94 private boolean trustedMatch = false;
This really means "true if the cacerts constraint enabled AND the chain
is anchored by a cacert". Can you add that to the comment so it is more
clear? Maybe the variable name should be changed to
"caCertConstraintApplies".
97 private static final boolean checkerEnabled =
98 certPathDefaultConstraints.checkProperty("cacerts");
Call this cacertsEnabled to be more specific?
159 // Check if the 'cert' is in the trust anchor file (cacerts)
160 private static boolean isAnchor(X509Certificate cert) {
Call this caCertConstraintApplies()?
161 if (!checkerEnabled) {
162 return false;
163 }
I'm not sure I understand why
165 if (debug != null)
debug.println("AlgorithmChecker.isAnchor: " +
Suggest the following to improve readability:
if (debug != null) {
debug.println("AlgorithmChecker.isAnchor: " +
cert.getSigAlgName());
}
DisabledAlgorithmConstraints
----------------------------
62 private final String propertyName;
Doesn't seem to be used; delete?
138 public final void permits(Set<CryptoPrimitive> primitives,
139 X509Certificate cert) throws CertPathValidatorException {
Doesn't seem to be used; delete?
246 if (!constraintsMap.containsKey(algorithm)) {
247 constraintsMap.putIfAbsent(algorithm, new
HashSet<>());
248 }
You can replace this with:
constraintsMap.computeIfAbsent(algorithm, k -> new HashSet<>());
Same comment on lines 280-282.
251 algorithm.toUpperCase(Locale.ENGLISH);
Shouldn't you also do this before adding it to the map on line 246-7?
253 if (debug != null) debug.println("Constraints len: " +
254 rComma.substring(space).split("&").length);
I suspect this debugging is more useful for debugging your own code. But
we shouldn't include it unless it is helpful for analyzing
real issues, as the debug log files are long enough :) Same comment
applies to other debugging statements (ex: lines 324-9).
287 lastConstraint = c;
This seems like a bug since it is overwriting what was just done on line
285. Should this be moved to right after line 283?
Also, if you had a constraint like: "RSA keySize < 1024, RSA keySize >
4096" it looks like the 2nd RSA constraint will replace the first
constraint, which isn't what I think is intended.
293 public Set<Constraint> getConstraints(Key key) {
I think you can remove this method and just change line 304 to:
Set<Constraint> set = getConstraints(key.getAlgorithm());
393 public boolean permits(Key key) {
403 public void permits(CertificateParameters cp) throws
CertPathValidatorException {
These should probably be abstract.
416 CertConstraint(String algo, String s) {
Better name for "s"?
--Sean
More information about the security-dev
mailing list