Commit c4ab1b95 authored by Chad Brubaker's avatar Chad Brubaker
Browse files

Cache intermediate CA separately

Intermediate CAs are cached in order to support servers that fail to
sent a complete chain to a root. These certificates should be cached to
support these servers but these certificates must not be trusted as
trust anchors. Store them separately to prevent confusion between
trusted roots and cached intermediates.

(cherry-picked from commit 198aca1f)
Bug: 26232830
Change-Id: I520f50729b55fc7412c7d133335bc9e3c190bbf6
parent de55e62f
......@@ -78,11 +78,16 @@ public final class TrustManagerImpl implements X509TrustManager {
private final CertPathValidator validator;
/**
* An index of TrustAnchor instances that we've seen. Unlike the
* TrustedCertificateStore, this may contain intermediate CAs.
* An index of TrustAnchor instances that we've seen.
*/
private final TrustedCertificateIndex trustedCertificateIndex;
/**
* An index of intermediate certificates that we've seen. These certificates are NOT implicitly
* trusted and must still form a valid chain to an anchor.
*/
private final TrustedCertificateIndex intermediateIndex;
/**
* This is lazily initialized in the AndroidCAStore case since it
* forces us to bring all the CAs into memory. In the
......@@ -160,6 +165,7 @@ public final class TrustManagerImpl implements X509TrustManager {
this.validator = validatorLocal;
this.factory = factoryLocal;
this.trustedCertificateIndex = trustedCertificateIndexLocal;
this.intermediateIndex = new TrustedCertificateIndex();
this.acceptedIssuers = acceptedIssuersLocal;
this.err = errLocal;
}
......@@ -336,7 +342,7 @@ public final class TrustManagerImpl implements X509TrustManager {
// will have been removed in
// cleanupCertChainAndFindTrustAnchors. http://b/3404902
for (int i = 1; i < newChain.length; i++) {
trustedCertificateIndex.index(newChain[i]);
intermediateIndex.index(newChain[i]);
}
} catch (InvalidAlgorithmParameterException e) {
throw new CertificateException(e);
......@@ -397,7 +403,28 @@ public final class TrustManagerImpl implements X509TrustManager {
}
}
// 2. Find the trust anchor in the chain, if any
// 2. Add any missing intermediates to the chain
while (true) {
TrustAnchor nextIntermediate =
intermediateIndex.findByIssuerAndSignature(chain[currIndex]);
if (nextIntermediate == null) {
break;
}
// Append intermediate
X509Certificate cert = nextIntermediate.getTrustedCert();
// don't mutate original chain, which may be directly from an SSLSession
if (chain == original) {
chain = original.clone();
}
// Grow the chain if needed
if (currIndex == chain.length - 1) {
chain = Arrays.copyOf(chain, chain.length * 2);
}
chain[currIndex + 1] = cert;
currIndex++;
}
// 3. Find the trust anchor in the chain, if any
int anchorIndex;
for (anchorIndex = 0; anchorIndex <= currIndex; anchorIndex++) {
// If the current cert is a TrustAnchor, we can ignore the rest of the chain.
......@@ -409,13 +436,13 @@ public final class TrustManagerImpl implements X509TrustManager {
}
}
// 3. If the chain is now shorter, copy to an appropriately sized array.
// 4. If the chain is now shorter, copy to an appropriately sized array.
int chainLength = anchorIndex;
X509Certificate[] newChain = ((chainLength == chain.length)
? chain
: Arrays.copyOf(chain, chainLength));
// 4. If we didn't find a trust anchor earlier, look for one now
// 5. If we didn't find a trust anchor earlier, look for one now
if (trustAnchors.isEmpty()) {
TrustAnchor trustAnchor = findTrustAnchorByIssuerAndSignature(newChain[anchorIndex-1]);
if (trustAnchor != null) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment