diff --git a/src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java b/src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java index db36c0e4a44334ac02b40ecf7185c7fa24766d96..0ad5387b3248977c23e79f565d96f3b9bdc185ce 100644 --- a/src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java +++ b/src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java @@ -36,9 +36,7 @@ import java.util.Date; import sun.security.util.Debug; import sun.security.util.DerInputStream; -import sun.security.util.DerOutputStream; import sun.security.x509.SerialNumber; -import sun.security.x509.KeyIdentifier; import sun.security.x509.AuthorityKeyIdentifierExtension; /** @@ -131,13 +129,7 @@ class AdaptableX509CertSelector extends X509CertSelector { serial = null; if (ext != null) { - KeyIdentifier akid = (KeyIdentifier)ext.get( - AuthorityKeyIdentifierExtension.KEY_ID); - if (akid != null) { - DerOutputStream derout = new DerOutputStream(); - derout.putOctetString(akid.getIdentifier()); - ski = derout.toByteArray(); - } + ski = ext.getEncodedKeyIdentifier(); SerialNumber asn = (SerialNumber)ext.get( AuthorityKeyIdentifierExtension.SERIAL_NUMBER); if (asn != null) { diff --git a/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java b/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java index 7b1076ef34cfbd642db563a808d3051adfde5afd..086e73f64c938fa1b404c699bd2aa5fa11bc23ba 100644 --- a/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java +++ b/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java @@ -33,7 +33,6 @@ import javax.security.auth.x500.X500Principal; import java.util.*; import sun.security.util.Debug; -import sun.security.util.DerOutputStream; import static sun.security.x509.PKIXExtensions.*; import sun.security.x509.*; @@ -608,12 +607,9 @@ public class DistributionPointFetcher { AuthorityKeyIdentifierExtension akidext = crlImpl.getAuthKeyIdExtension(); if (akidext != null) { - KeyIdentifier akid = (KeyIdentifier)akidext.get( - AuthorityKeyIdentifierExtension.KEY_ID); - if (akid != null) { - DerOutputStream derout = new DerOutputStream(); - derout.putOctetString(akid.getIdentifier()); - certSel.setSubjectKeyIdentifier(derout.toByteArray()); + byte[] kid = akidext.getEncodedKeyIdentifier(); + if (kid != null) { + certSel.setSubjectKeyIdentifier(kid); } SerialNumber asn = (SerialNumber)akidext.get( diff --git a/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java b/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java index 7f30d3b0ceb7f732e8142485d5e592637b044832..3c86d6206ffbfcff0e5816ecf1259f990a4c580c 100644 --- a/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java +++ b/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java @@ -46,9 +46,10 @@ import sun.security.provider.certpath.PKIX.BuilderParams; import sun.security.util.Debug; 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.X500Name; -import sun.security.x509.AuthorityKeyIdentifierExtension; +import sun.security.x509.X509CertImpl; /** * This class represents a forward builder, which is able to retrieve @@ -69,7 +70,6 @@ class ForwardBuilder extends Builder { private AdaptableX509CertSelector caSelector; private X509CertSelector caTargetSelector; TrustAnchor trustAnchor; - private Comparator comparator; private boolean searchAllCertStores = true; /** @@ -93,7 +93,6 @@ class ForwardBuilder extends Builder { trustedSubjectDNs.add(anchor.getCA()); } } - comparator = new PKIXCertComparator(trustedSubjectDNs); this.searchAllCertStores = searchAllCertStores; } @@ -122,6 +121,8 @@ class ForwardBuilder extends Builder { * As each cert is added, it is sorted based on the PKIXCertComparator * algorithm. */ + Comparator comparator = + new PKIXCertComparator(trustedSubjectDNs, currState.cert); Set certs = new TreeSet<>(comparator); /* @@ -264,14 +265,6 @@ class ForwardBuilder extends Builder { CertPathHelper.setPathToNames (caSelector, currentState.subjectNamesTraversed); - /* - * Facilitate certification path construction with authority - * key identifier and subject key identifier. - */ - AuthorityKeyIdentifierExtension akidext = - currentState.cert.getAuthorityKeyIdentifierExtension(); - caSelector.setSkiAndSerialNumber(akidext); - /* * check the validity period */ @@ -404,41 +397,68 @@ class ForwardBuilder extends Builder { * * Preference order for current cert: * - * 1) Issuer matches a trusted subject + * 1) The key identifier of an AKID extension (if present) in the + * previous certificate matches the key identifier in the SKID extension + * + * 2) Issuer matches a trusted subject * Issuer: ou=D,ou=C,o=B,c=A * - * 2) Issuer is a descendant of a trusted subject (in order of + * 3) Issuer is a descendant of a trusted subject (in order of * number of links to the trusted subject) * a) Issuer: ou=E,ou=D,ou=C,o=B,c=A [links=1] * b) Issuer: ou=F,ou=E,ou=D,ou=C,ou=B,c=A [links=2] * - * 3) Issuer is an ancestor of a trusted subject (in order of number of + * 4) Issuer is an ancestor of a trusted subject (in order of number of * links to the trusted subject) * a) Issuer: ou=C,o=B,c=A [links=1] * b) Issuer: o=B,c=A [links=2] * - * 4) Issuer is in the same namespace as a trusted subject (in order of + * 5) Issuer is in the same namespace as a trusted subject (in order of * number of links to the trusted subject) * a) Issuer: ou=G,ou=C,o=B,c=A [links=2] * b) Issuer: ou=H,o=B,c=A [links=3] * - * 5) Issuer is an ancestor of certificate subject (in order of number + * 6) Issuer is an ancestor of certificate subject (in order of number * of links to the certificate subject) * a) Issuer: ou=K,o=J,c=A * Subject: ou=L,ou=K,o=J,c=A * b) Issuer: o=J,c=A * Subject: ou=L,ou=K,0=J,c=A * - * 6) Any other certificates + * 7) Any other certificates */ static class PKIXCertComparator implements Comparator { - final static String METHOD_NME = "PKIXCertComparator.compare()"; + static final String METHOD_NME = "PKIXCertComparator.compare()"; private final Set trustedSubjectDNs; + private final X509CertSelector certSkidSelector; - PKIXCertComparator(Set trustedSubjectDNs) { + PKIXCertComparator(Set trustedSubjectDNs, + X509CertImpl previousCert) throws IOException { this.trustedSubjectDNs = trustedSubjectDNs; + this.certSkidSelector = getSelector(previousCert); + } + + /** + * Returns an X509CertSelector for matching on the authority key + * identifier, or null if not applicable. + */ + private X509CertSelector getSelector(X509CertImpl previousCert) + throws IOException { + if (previousCert != null) { + AuthorityKeyIdentifierExtension akidExt = + previousCert.getAuthorityKeyIdentifierExtension(); + if (akidExt != null) { + byte[] skid = akidExt.getEncodedKeyIdentifier(); + if (skid != null) { + X509CertSelector selector = new X509CertSelector(); + selector.setSubjectKeyIdentifier(skid); + return selector; + } + } + } + return null; } /** @@ -462,6 +482,16 @@ class ForwardBuilder extends Builder { // if certs are the same, return 0 if (oCert1.equals(oCert2)) return 0; + // If akid/skid match then it is preferable + if (certSkidSelector != null) { + if (certSkidSelector.match(oCert1)) { + return -1; + } + if (certSkidSelector.match(oCert2)) { + return 1; + } + } + X500Principal cIssuer1 = oCert1.getIssuerX500Principal(); X500Principal cIssuer2 = oCert2.getIssuerX500Principal(); X500Name cIssuer1Name = X500Name.asX500Name(cIssuer1); diff --git a/src/share/classes/sun/security/x509/AuthorityKeyIdentifierExtension.java b/src/share/classes/sun/security/x509/AuthorityKeyIdentifierExtension.java index afd7c99683da8b792ec98e23893617eefe9b309b..9e76a3a75afe5062194e2a8eb2fa556d34338787 100644 --- a/src/share/classes/sun/security/x509/AuthorityKeyIdentifierExtension.java +++ b/src/share/classes/sun/security/x509/AuthorityKeyIdentifierExtension.java @@ -307,4 +307,16 @@ implements CertAttrSet { public String getName() { return (NAME); } + + /** + * Return the encoded key identifier, or null if not specified. + */ + public byte[] getEncodedKeyIdentifier() throws IOException { + if (id != null) { + DerOutputStream derOut = new DerOutputStream(); + id.encode(derOut); + return derOut.toByteArray(); + } + return null; + } }