X509Util.java revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package org.chromium.net;
6
7import android.util.Log;
8
9import java.io.ByteArrayInputStream;
10import java.security.KeyStore;
11import java.security.KeyStoreException;
12import java.security.NoSuchAlgorithmException;
13import java.security.cert.CertificateException;
14import java.security.cert.CertificateFactory;
15import java.security.cert.X509Certificate;
16
17import javax.net.ssl.TrustManager;
18import javax.net.ssl.TrustManagerFactory;
19import javax.net.ssl.X509TrustManager;
20
21public class X509Util {
22
23    private static final String TAG = X509Util.class.getName();
24
25    private static CertificateFactory sCertificateFactory;
26
27    /**
28     * Default sources of authentication trust decisions and certificate object
29     * creation.
30     */
31    private static X509TrustManager sDefaultTrustManager;
32
33    /**
34     * Ensures that |sCertificateFactory| and |sDefaultTrustManager| are
35     * initialized.
36     */
37    private static synchronized void ensureInitialized() throws CertificateException,
38            KeyStoreException, NoSuchAlgorithmException {
39        if (sCertificateFactory == null) {
40            sCertificateFactory = CertificateFactory.getInstance("X.509");
41        }
42        if (sDefaultTrustManager == null) {
43            sDefaultTrustManager = X509Util.createDefaultTrustManager();
44        }
45    }
46
47    /**
48     * Creates a TrustManagerFactory and returns the X509TrustManager instance
49     * if one can be found.
50     *
51     * @throws CertificateException,KeyStoreException,NoSuchAlgorithmException
52     *             on error initializing the TrustManager.
53     */
54    private static X509TrustManager createDefaultTrustManager()
55            throws KeyStoreException, NoSuchAlgorithmException {
56        String algorithm = TrustManagerFactory.getDefaultAlgorithm();
57        TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
58        tmf.init((KeyStore) null);
59
60        for (TrustManager tm : tmf.getTrustManagers()) {
61            if (tm instanceof X509TrustManager) {
62                return (X509TrustManager) tm;
63            }
64        }
65        return null;
66    }
67
68    /**
69     * Convert a DER encoded certificate to an X509Certificate
70     */
71    public static X509Certificate createCertificateFromBytes(byte[] derBytes) throws
72            CertificateException, KeyStoreException, NoSuchAlgorithmException {
73        ensureInitialized();
74        return (X509Certificate) sCertificateFactory.generateCertificate(
75                new ByteArrayInputStream(derBytes));
76    }
77
78    public static boolean verifyServerCertificates(byte[][] certChain, String authType)
79            throws CertificateException, KeyStoreException, NoSuchAlgorithmException {
80        if (certChain == null || certChain.length == 0 || certChain[0] == null) {
81            throw new IllegalArgumentException("Expected non-null and non-empty certificate " +
82                    "chain passed as |certChain|. |certChain|=" + certChain);
83        }
84
85        ensureInitialized();
86        X509Certificate[] serverCertificates = new X509Certificate[certChain.length];
87        for (int i = 0; i < certChain.length; ++i) {
88            serverCertificates[i] = createCertificateFromBytes(certChain[i]);
89        }
90
91        try {
92            sDefaultTrustManager.checkServerTrusted(serverCertificates, authType);
93            return true;
94        } catch (CertificateException e) {
95            Log.i(TAG, "failed to validate the certificate chain, error: " +
96                    e.getMessage());
97        }
98        return false;
99    }
100
101}
102