diff --git a/src/java.base/share/classes/java/security/cert/CertPathHelperImpl.java b/src/java.base/share/classes/java/security/cert/CertPathHelperImpl.java index bd6545a7357..3da6cb3dd4f 100644 --- a/src/java.base/share/classes/java/security/cert/CertPathHelperImpl.java +++ b/src/java.base/share/classes/java/security/cert/CertPathHelperImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2023, 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 @@ -25,12 +25,10 @@ package java.security.cert; -import java.util.*; +import java.util.Date; import sun.security.provider.certpath.CertPathHelper; -import sun.security.x509.GeneralNameInterface; - /** * Helper class that allows the Sun CertPath provider to access * implementation dependent APIs in CertPath framework. @@ -55,11 +53,6 @@ class CertPathHelperImpl extends CertPathHelper { } } - protected void implSetPathToNames(X509CertSelector sel, - Set names) { - sel.setPathToNamesInternal(names); - } - protected void implSetDateAndTime(X509CRLSelector sel, Date date, long skew) { sel.setDateAndTime(date, skew); } diff --git a/src/java.base/share/classes/java/security/cert/X509CertSelector.java b/src/java.base/share/classes/java/security/cert/X509CertSelector.java index c472d58b473..9b712411a61 100644 --- a/src/java.base/share/classes/java/security/cert/X509CertSelector.java +++ b/src/java.base/share/classes/java/security/cert/X509CertSelector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, 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 @@ -87,10 +87,6 @@ public class X509CertSelector implements CertSelector { private static final ObjectIdentifier ANY_EXTENDED_KEY_USAGE = ObjectIdentifier.of(KnownOIDs.anyExtendedKeyUsage); - static { - CertPathHelperImpl.initialize(); - } - private BigInteger serialNumber; private X500Principal issuer; private X500Principal subject; @@ -1127,14 +1123,6 @@ public class X509CertSelector implements CertSelector { } } - // called from CertPathHelper - void setPathToNamesInternal(Set names) { - // set names to non-null dummy value - // this breaks getPathToNames() - pathToNames = Collections.>emptySet(); - pathToGeneralNames = names; - } - /** * Adds a name to the pathToNames criterion. The {@code X509Certificate} * must not include name constraints that would prohibit building a diff --git a/src/java.base/share/classes/sun/security/provider/certpath/CertPathHelper.java b/src/java.base/share/classes/sun/security/provider/certpath/CertPathHelper.java index 3675209e03d..203b92ce30a 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/CertPathHelper.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/CertPathHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2023, 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 @@ -26,14 +26,10 @@ package sun.security.provider.certpath; import java.util.Date; -import java.util.Set; import java.security.cert.TrustAnchor; -import java.security.cert.X509CertSelector; import java.security.cert.X509CRLSelector; -import sun.security.x509.GeneralNameInterface; - /** * Helper class that allows access to JDK specific known-public methods in the * java.security.cert package. It relies on a subclass in the @@ -55,18 +51,10 @@ public abstract class CertPathHelper { // empty } - protected abstract void implSetPathToNames(X509CertSelector sel, - Set names); - protected abstract void implSetDateAndTime(X509CRLSelector sel, Date date, long skew); protected abstract boolean implIsJdkCA(TrustAnchor anchor); - static void setPathToNames(X509CertSelector sel, - Set names) { - instance.implSetPathToNames(sel, names); - } - public static void setDateAndTime(X509CRLSelector sel, Date date, long skew) { instance.implSetDateAndTime(sel, date, skew); } diff --git a/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java b/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java index 26f97efc3d9..125af069203 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java @@ -47,7 +47,6 @@ import sun.security.x509.AccessDescription; import sun.security.x509.AuthorityInfoAccessExtension; import sun.security.x509.AuthorityKeyIdentifierExtension; import static sun.security.x509.PKIXExtensions.*; -import sun.security.x509.SubjectAlternativeNameExtension; import sun.security.x509.X500Name; import sun.security.x509.X509CertImpl; @@ -257,14 +256,6 @@ final class ForwardBuilder extends Builder { */ caSelector.setSubject(currentState.issuerDN); - /* - * Match on subjectNamesTraversed (both DNs and AltNames) - * (checks that current cert's name constraints permit it - * to certify all the DNs and AltNames that have been traversed) - */ - CertPathHelper.setPathToNames - (caSelector, currentState.subjectNamesTraversed); - /* * check the validity period */ @@ -697,19 +688,6 @@ final class ForwardBuilder extends Builder { // Don't bother to verify untrusted certificate more. currState.untrustedChecker.check(cert, Collections.emptySet()); - /* - * Abort if we encounter the same certificate or a certificate with - * the same public key, subject DN, and subjectAltNames as a cert - * that is already in path. - */ - for (X509Certificate cpListCert : certPathList) { - if (repeated(cpListCert, cert)) { - throw new CertPathValidatorException( - "cert with repeated subject, public key, and " + - "subjectAltNames detected"); - } - } - /* check if trusted cert */ boolean isTrustedCert = trustedCerts.contains(cert); @@ -787,49 +765,6 @@ final class ForwardBuilder extends Builder { } } - /** - * Return true if two certificates are equal or have the same subject, - * public key, and subject alternative names. - */ - private static boolean repeated( - X509Certificate currCert, X509Certificate nextCert) { - if (currCert.equals(nextCert)) { - return true; - } - return (currCert.getSubjectX500Principal().equals( - nextCert.getSubjectX500Principal()) && - currCert.getPublicKey().equals(nextCert.getPublicKey()) && - altNamesEqual(currCert, nextCert)); - } - - /** - * Return true if two certificates have the same subject alternative names. - */ - private static boolean altNamesEqual( - X509Certificate currCert, X509Certificate nextCert) { - X509CertImpl curr, next; - try { - curr = X509CertImpl.toImpl(currCert); - next = X509CertImpl.toImpl(nextCert); - } catch (CertificateException ce) { - return false; - } - - SubjectAlternativeNameExtension currAltNameExt = - curr.getSubjectAlternativeNameExtension(); - SubjectAlternativeNameExtension nextAltNameExt = - next.getSubjectAlternativeNameExtension(); - if (currAltNameExt != null) { - if (nextAltNameExt == null) { - return false; - } - return Arrays.equals(currAltNameExt.getExtensionValue(), - nextAltNameExt.getExtensionValue()); - } else { - return (nextAltNameExt == null); - } - } - /** * Verifies whether the input certificate completes the path. * First checks the cert against each trust anchor that was specified, diff --git a/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java b/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java index c93f0bcb3a0..537b6b8266f 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java @@ -31,17 +31,11 @@ import java.security.cert.CertPathValidatorException; import java.security.cert.PKIXCertPathChecker; import java.security.cert.X509Certificate; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.ListIterator; import javax.security.auth.x500.X500Principal; import sun.security.util.Debug; -import sun.security.x509.SubjectAlternativeNameExtension; -import sun.security.x509.GeneralNames; -import sun.security.x509.GeneralName; -import sun.security.x509.GeneralNameInterface; -import sun.security.x509.X500Name; import sun.security.x509.X509CertImpl; /** @@ -61,9 +55,6 @@ class ForwardState implements State { /* The last cert in the path */ X509CertImpl cert; - /* The set of subjectDNs and subjectAltNames of all certs in the path */ - HashSet subjectNamesTraversed; - /* * The number of intermediate CA certs which have been traversed so * far in the path @@ -73,7 +64,6 @@ class ForwardState implements State { /* Flag indicating if state is initial (path is just starting) */ private boolean init = true; - /* the untrusted certificates checker */ UntrustedChecker untrustedChecker; @@ -103,8 +93,6 @@ class ForwardState implements State { "\n issuerDN of last cert: " + issuerDN + "\n traversedCACerts: " + traversedCACerts + "\n init: " + init + - "\n subjectNamesTraversed: \n" + - subjectNamesTraversed + "\n selfIssued: " + selfIssued + "\n" + "]\n"; } @@ -117,7 +105,6 @@ class ForwardState implements State { public void initState(List certPathCheckers) throws CertPathValidatorException { - subjectNamesTraversed = new HashSet<>(); traversedCACerts = 0; /* @@ -167,22 +154,6 @@ class ForwardState implements State { } } - /* update subjectNamesTraversed only if this is the EE cert or if - this cert is not self-issued */ - if (init || !selfIssued) { - X500Principal subjName = cert.getSubjectX500Principal(); - subjectNamesTraversed.add(X500Name.asX500Name(subjName)); - - SubjectAlternativeNameExtension subjAltNameExt - = icert.getSubjectAlternativeNameExtension(); - if (subjAltNameExt != null) { - GeneralNames gNames = subjAltNameExt.getNames(); - for (GeneralName gName : gNames.names()) { - subjectNamesTraversed.add(gName.getName()); - } - } - } - init = false; } @@ -190,10 +161,6 @@ class ForwardState implements State { * Clone current state. The state is cloned as each cert is * added to the path. This is necessary if backtracking occurs, * and a prior state needs to be restored. - * - * Note that this is a SMART clone. Not all fields are fully copied, - * because some of them will - * not have their contents modified by subsequent calls to updateState. */ @Override @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly @@ -213,13 +180,6 @@ class ForwardState implements State { } } - /* - * Shallow copy traversed names. There is no need to - * deep copy contents, since the elements of the Set - * are never modified by subsequent calls to updateState(). - */ - clonedState.subjectNamesTraversed - = (HashSet)subjectNamesTraversed.clone(); return clonedState; } catch (CloneNotSupportedException e) { throw new InternalError(e.toString(), e); diff --git a/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java b/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java index 8c9081b3d9f..c4e31cf7947 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java @@ -33,6 +33,7 @@ import java.security.cert.*; import java.security.cert.CertPathValidatorException.BasicReason; import java.security.cert.PKIXReason; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -42,6 +43,7 @@ import javax.security.auth.x500.X500Principal; import sun.security.provider.certpath.PKIX.BuilderParams; import static sun.security.x509.PKIXExtensions.*; +import sun.security.x509.SubjectAlternativeNameExtension; import sun.security.x509.X509CertImpl; import sun.security.util.Debug; @@ -265,7 +267,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { */ Collection certs = builder.getMatchingCerts(currentState, buildParams.certStores()); - List vertices = addVertices(certs, adjList); + List vertices = addVertices(certs, adjList, cpList); if (debug != null) { debug.println("SunCertPathBuilder.depthFirstSearchForward(): " + "certs.size=" + vertices.size()); @@ -325,33 +327,9 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { * cert (which is signed by the trusted public key), but * don't add it yet to the cpList */ - if (builder.trustAnchor.getTrustedCert() == null) { - appendedCerts.add(0, cert); - } - - Set initExpPolSet = - Collections.singleton(PolicyChecker.ANY_POLICY); - - PolicyNodeImpl rootNode = new PolicyNodeImpl(null, - PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false); - - List checkers = new ArrayList<>(); - PolicyChecker policyChecker - = new PolicyChecker(buildParams.initialPolicies(), - appendedCerts.size(), - buildParams.explicitPolicyRequired(), - buildParams.policyMappingInhibited(), - buildParams.anyPolicyInhibited(), - buildParams.policyQualifiersRejected(), - rootNode); - checkers.add(policyChecker); - - // add the algorithm checker - checkers.add(new AlgorithmChecker(builder.trustAnchor, - buildParams.timestamp(), buildParams.variant())); - PublicKey rootKey = cert.getPublicKey(); if (builder.trustAnchor.getTrustedCert() == null) { + appendedCerts.add(0, cert); rootKey = builder.trustAnchor.getCAPublicKey(); if (debug != null) debug.println( @@ -363,11 +341,35 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { (cert.getSubjectX500Principal(), rootKey, null); // add the basic checker + List checkers = new ArrayList<>(); BasicChecker basicChecker = new BasicChecker(anchor, buildParams.date(), buildParams.sigProvider(), true); checkers.add(basicChecker); + Set initExpPolSet = + Collections.singleton(PolicyChecker.ANY_POLICY); + + PolicyNodeImpl rootNode = new PolicyNodeImpl(null, + PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false); + + PolicyChecker policyChecker + = new PolicyChecker(buildParams.initialPolicies(), + appendedCerts.size(), + buildParams.explicitPolicyRequired(), + buildParams.policyMappingInhibited(), + buildParams.anyPolicyInhibited(), + buildParams.policyQualifiersRejected(), + rootNode); + checkers.add(policyChecker); + + // add the constraints checker + checkers.add(new ConstraintsChecker(appendedCerts.size())); + + // add the algorithm checker + checkers.add(new AlgorithmChecker(builder.trustAnchor, + buildParams.timestamp(), buildParams.variant())); + buildParams.setCertPath(cf.generateCertPath(appendedCerts)); @@ -563,18 +565,79 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { * adjacency list. */ private static List addVertices(Collection certs, - List> adjList) + List> adjList, + List cpList) { List l = adjList.get(adjList.size() - 1); for (X509Certificate cert : certs) { - Vertex v = new Vertex(cert); - l.add(v); + boolean repeated = false; + for (X509Certificate cpListCert : cpList) { + /* + * Ignore if we encounter the same certificate or a + * certificate with the same public key, subject DN, and + * subjectAltNames as a cert that is already in path. + */ + if (repeated(cpListCert, cert)) { + if (debug != null) { + debug.println("cert with repeated subject, " + + "public key, and subjectAltNames detected"); + } + repeated = true; + break; + } + } + if (!repeated) { + l.add(new Vertex(cert)); + } } return l; } + /** + * Return true if two certificates are equal or have the same subject, + * public key, and subject alternative names. + */ + private static boolean repeated( + X509Certificate currCert, X509Certificate nextCert) { + if (currCert.equals(nextCert)) { + return true; + } + return (currCert.getSubjectX500Principal().equals( + nextCert.getSubjectX500Principal()) && + currCert.getPublicKey().equals(nextCert.getPublicKey()) && + altNamesEqual(currCert, nextCert)); + } + + /** + * Return true if two certificates have the same subject alternative names. + */ + private static boolean altNamesEqual( + X509Certificate currCert, X509Certificate nextCert) { + X509CertImpl curr, next; + try { + curr = X509CertImpl.toImpl(currCert); + next = X509CertImpl.toImpl(nextCert); + } catch (CertificateException ce) { + return false; + } + + SubjectAlternativeNameExtension currAltNameExt = + curr.getSubjectAlternativeNameExtension(); + SubjectAlternativeNameExtension nextAltNameExt = + next.getSubjectAlternativeNameExtension(); + if (currAltNameExt != null) { + if (nextAltNameExt == null) { + return false; + } + return Arrays.equals(currAltNameExt.getExtensionValue(), + nextAltNameExt.getExtensionValue()); + } else { + return (nextAltNameExt == null); + } + } + /** * Returns true if trust anchor certificate matches specified * certificate constraints.