Skip to content

Commit be492cb

Browse files
chadbrubakerandi34
authored andcommitted
DO NOT MERGE 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 198aca1fb638a2a98e89fb9f284108ad576d0c3b) Bug: 26232830 Change-Id: I520f50729b55fc7412c7d133335bc9e3c190bbf6 (cherry picked from commit 1cca3cd)
1 parent de823c2 commit be492cb

File tree

1 file changed

+33
-6
lines changed

1 file changed

+33
-6
lines changed

crypto/src/main/java/org/conscrypt/TrustManagerImpl.java

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,16 @@ public final class TrustManagerImpl implements X509TrustManager {
7272
private final CertPathValidator validator;
7373

7474
/**
75-
* An index of TrustAnchor instances that we've seen. Unlike the
76-
* TrustedCertificateStore, this may contain intermediate CAs.
75+
* An index of TrustAnchor instances that we've seen.
7776
*/
7877
private final TrustedCertificateIndex trustedCertificateIndex;
7978

79+
/**
80+
* An index of intermediate certificates that we've seen. These certificates are NOT implicitly
81+
* trusted and must still form a valid chain to an anchor.
82+
*/
83+
private final TrustedCertificateIndex intermediateIndex;
84+
8085
/**
8186
* This is lazily initialized in the AndroidCAStore case since it
8287
* forces us to bring all the CAs into memory. In the
@@ -145,6 +150,7 @@ public TrustManagerImpl(KeyStore keyStore, CertPinManager manager) {
145150
this.validator = validatorLocal;
146151
this.factory = factoryLocal;
147152
this.trustedCertificateIndex = trustedCertificateIndexLocal;
153+
this.intermediateIndex = new TrustedCertificateIndex();
148154
this.acceptedIssuers = acceptedIssuersLocal;
149155
this.err = errLocal;
150156
}
@@ -300,7 +306,7 @@ private List<X509Certificate> checkTrusted(X509Certificate[] chain, String authT
300306
// will have been removed in
301307
// cleanupCertChainAndFindTrustAnchors. http://b/3404902
302308
for (int i = 1; i < newChain.length; i++) {
303-
trustedCertificateIndex.index(newChain[i]);
309+
intermediateIndex.index(newChain[i]);
304310
}
305311
} catch (InvalidAlgorithmParameterException e) {
306312
throw new CertificateException(e);
@@ -361,7 +367,28 @@ private X509Certificate[] cleanupCertChainAndFindTrustAnchors(X509Certificate[]
361367
}
362368
}
363369

364-
// 2. Find the trust anchor in the chain, if any
370+
// 2. Add any missing intermediates to the chain
371+
while (true) {
372+
TrustAnchor nextIntermediate =
373+
intermediateIndex.findByIssuerAndSignature(chain[currIndex]);
374+
if (nextIntermediate == null) {
375+
break;
376+
}
377+
// Append intermediate
378+
X509Certificate cert = nextIntermediate.getTrustedCert();
379+
// don't mutate original chain, which may be directly from an SSLSession
380+
if (chain == original) {
381+
chain = original.clone();
382+
}
383+
// Grow the chain if needed
384+
if (currIndex == chain.length - 1) {
385+
chain = Arrays.copyOf(chain, chain.length * 2);
386+
}
387+
chain[currIndex + 1] = cert;
388+
currIndex++;
389+
}
390+
391+
// 3. Find the trust anchor in the chain, if any
365392
int anchorIndex;
366393
for (anchorIndex = 0; anchorIndex <= currIndex; anchorIndex++) {
367394
// If the current cert is a TrustAnchor, we can ignore the rest of the chain.
@@ -373,13 +400,13 @@ private X509Certificate[] cleanupCertChainAndFindTrustAnchors(X509Certificate[]
373400
}
374401
}
375402

376-
// 3. If the chain is now shorter, copy to an appropriately sized array.
403+
// 4. If the chain is now shorter, copy to an appropriately sized array.
377404
int chainLength = anchorIndex;
378405
X509Certificate[] newChain = ((chainLength == chain.length)
379406
? chain
380407
: Arrays.copyOf(chain, chainLength));
381408

382-
// 4. If we didn't find a trust anchor earlier, look for one now
409+
// 5. If we didn't find a trust anchor earlier, look for one now
383410
if (trustAnchors.isEmpty()) {
384411
TrustAnchor trustAnchor = findTrustAnchorByIssuerAndSignature(newChain[anchorIndex-1]);
385412
if (trustAnchor != null) {

0 commit comments

Comments
 (0)