mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8309966: Enhanced TLS connections
Reviewed-by: mschoene, hchao, rhalade, jnimeh
This commit is contained in:
parent
adca97b659
commit
7c80cb26df
6 changed files with 96 additions and 169 deletions
|
@ -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<GeneralNameInterface> names);
|
||||
|
||||
protected abstract void implSetDateAndTime(X509CRLSelector sel, Date date, long skew);
|
||||
|
||||
protected abstract boolean implIsJdkCA(TrustAnchor anchor);
|
||||
|
||||
static void setPathToNames(X509CertSelector sel,
|
||||
Set<GeneralNameInterface> names) {
|
||||
instance.implSetPathToNames(sel, names);
|
||||
}
|
||||
|
||||
public static void setDateAndTime(X509CRLSelector sel, Date date, long skew) {
|
||||
instance.implSetDateAndTime(sel, date, skew);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<GeneralNameInterface> 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<PKIXCertPathChecker> 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<GeneralNameInterface>)subjectNamesTraversed.clone();
|
||||
return clonedState;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new InternalError(e.toString(), e);
|
||||
|
|
|
@ -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<X509Certificate> certs =
|
||||
builder.getMatchingCerts(currentState, buildParams.certStores());
|
||||
List<Vertex> vertices = addVertices(certs, adjList);
|
||||
List<Vertex> 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<String> initExpPolSet =
|
||||
Collections.singleton(PolicyChecker.ANY_POLICY);
|
||||
|
||||
PolicyNodeImpl rootNode = new PolicyNodeImpl(null,
|
||||
PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false);
|
||||
|
||||
List<PKIXCertPathChecker> 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<PKIXCertPathChecker> checkers = new ArrayList<>();
|
||||
BasicChecker basicChecker = new BasicChecker(anchor,
|
||||
buildParams.date(),
|
||||
buildParams.sigProvider(),
|
||||
true);
|
||||
checkers.add(basicChecker);
|
||||
Set<String> 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<Vertex> addVertices(Collection<X509Certificate> certs,
|
||||
List<List<Vertex>> adjList)
|
||||
List<List<Vertex>> adjList,
|
||||
List<X509Certificate> cpList)
|
||||
{
|
||||
List<Vertex> 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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue