diff options
author | Android (Google) Code Review <android-gerrit@google.com> | 2009-09-21 20:36:39 -0400 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2009-09-21 20:36:39 -0400 |
commit | 6a93483621c8393a57b50dca1dadaeb48dcb6e38 (patch) | |
tree | 6eb68fecf0590cdf8c674cb6b0805808cf6ee9c5 | |
parent | bb0d360e281a26b3aa65bf9d7b616e1ef2519220 (diff) | |
parent | 5777f56ef4522e39ff9e41e967c399642fc6c6b4 (diff) | |
download | libcore-6a93483621c8393a57b50dca1dadaeb48dcb6e38.zip libcore-6a93483621c8393a57b50dca1dadaeb48dcb6e38.tar.gz libcore-6a93483621c8393a57b50dca1dadaeb48dcb6e38.tar.bz2 |
Merge change 26055 into eclair
* changes:
Replaced an O(N) algorithm with an O(1) algorithm. This shaves off 2/3 of the server cert checking time or ~200ms on Sapphire. This is in preparation for tripling the number of certs in an upcoming change.
-rw-r--r-- | security/src/main/java/org/bouncycastle/jce/provider/IndexedPKIXParameters.java | 17 | ||||
-rw-r--r-- | x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java | 85 |
2 files changed, 62 insertions, 40 deletions
diff --git a/security/src/main/java/org/bouncycastle/jce/provider/IndexedPKIXParameters.java b/security/src/main/java/org/bouncycastle/jce/provider/IndexedPKIXParameters.java index e8e834a..03679e2 100644 --- a/security/src/main/java/org/bouncycastle/jce/provider/IndexedPKIXParameters.java +++ b/security/src/main/java/org/bouncycastle/jce/provider/IndexedPKIXParameters.java @@ -109,7 +109,7 @@ public class IndexedPKIXParameters extends PKIXParameters { if (anchor != null) { return anchor; } - } catch (Exception e) { + } catch (Exception e) { Logger.getLogger(IndexedPKIXParameters.class.getName()).log( Level.WARNING, "Error encoding cert.", e); } @@ -125,6 +125,21 @@ public class IndexedPKIXParameters extends PKIXParameters { } /** + * Returns true if the given certificate is found in the trusted key + * store. + */ + public boolean isDirectlyTrusted(X509Certificate cert) { + try { + Bytes encoded = new Bytes(cert.getEncoded()); + return encodings.containsKey(encoded); + } catch (Exception e) { + Logger.getLogger(IndexedPKIXParameters.class.getName()).log( + Level.WARNING, "Error encoding cert.", e); + return false; + } + } + + /** * Wraps a byte[] and adds equals() and hashCode() support. */ static class Bytes { diff --git a/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java b/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java index 5c40b4e..543dfb2 100644 --- a/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java +++ b/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java @@ -44,11 +44,11 @@ import java.security.cert.CertificateEncodingException; // END android-added /** - * + * * TrustManager implementation. The implementation is based on CertPathValidator * PKIX and CertificateFactory X509 implementations. This implementations should * be provided by some certification provider. - * + * * @see javax.net.ssl.X509TrustManager */ public class TrustManagerImpl implements X509TrustManager { @@ -63,7 +63,7 @@ public class TrustManagerImpl implements X509TrustManager { /** * Creates trust manager implementation - * + * * @param ks */ public TrustManagerImpl(KeyStore ks) { @@ -144,70 +144,77 @@ public class TrustManagerImpl implements X509TrustManager { throws CertificateException { if (chain == null || chain.length == 0 || authType == null || authType.length() == 0) { - throw new IllegalArgumentException("null or zero-length parameter"); + throw new IllegalArgumentException( + "null or zero-length parameter"); } if (err != null) { throw new CertificateException(err); } - // BEGIN android-added - // Cater for degenerate special case where we can't - // establish an actual certificate chain the usual way, - // but have the peer certificate in our trust store. - if (isDirectlyTrustedCert(chain)) { - return; - } - // END android-added +// BEGIN android-changed + CertificateException ce = null; try { - // BEGIN android-changed - CertPath certPath = factory.generateCertPath(Arrays.asList(chain)); + CertPath certPath = factory.generateCertPath( + Arrays.asList(chain)); if (!Arrays.equals(chain[0].getEncoded(), - ((X509Certificate)certPath.getCertificates().get(0)) - .getEncoded())) { - // sanity check failed (shouldn't ever happen, but we are using pretty remote code) + certPath.getCertificates().get(0).getEncoded())) { + // Sanity check failed (shouldn't ever happen, but we are + // using pretty remote code) throw new CertificateException("Certificate chain error"); } validator.validate(certPath, params); - // END android-changed } catch (InvalidAlgorithmParameterException e) { - throw new CertificateException(e); + ce = new CertificateException(e); } catch (CertPathValidatorException e) { - throw new CertificateException(e); + ce = new CertificateException(e); + } + if (ce != null) { + // Caters to degenerate special case where we can't + // establish an actual certificate chain the usual way + // but have the peer certificate in our trust store. + if (!isDirectlyTrustedCert(chain)) { + throw ce; + } } } - // BEGIN android-added /** * Checks whether the given chain is just a certificate * that we have in our trust store. - * + * * @param chain The certificate chain. - * - * @return True if the certificate is in our trust store, false otherwise. + * + * @return True if the certificate is in our trust store, false otherwise. */ private boolean isDirectlyTrustedCert(X509Certificate[] chain) { byte[] questionable; if (chain.length == 1) { - try { - questionable = chain[0].getEncoded(); - Set<TrustAnchor> anchors = params.getTrustAnchors(); - - for (TrustAnchor trustAnchor : anchors) { - byte[] trusted = trustAnchor.getTrustedCert().getEncoded(); - - if (Arrays.equals(questionable, trusted)) { - return true; - } + if (params instanceof IndexedPKIXParameters) { + IndexedPKIXParameters index = (IndexedPKIXParameters) params; + return index.isDirectlyTrusted(chain[0]); + } else { + try { + questionable = chain[0].getEncoded(); + Set<TrustAnchor> anchors = params.getTrustAnchors(); + + for (TrustAnchor trustAnchor : anchors) { + byte[] trusted = trustAnchor.getTrustedCert() + .getEncoded(); + if (Arrays.equals(questionable, trusted)) { + return true; + } + } + } catch (CertificateEncodingException e) { + // Ignore. + } } - } catch (CertificateEncodingException e) { - // Ignore. - } + } return false; } - // END android-added - +// END android-changed + /** * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers() */ |