// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.security.KeyChain;
import android.security.KeyChainAliasCallback;
import android.security.KeyChainException;
import android.util.Log;

import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.base.ThreadUtils;
import org.chromium.net.AndroidPrivateKey;
import org.chromium.net.DefaultAndroidKeyStore;
import org.chromium.ui.base.WindowAndroid;

import java.security.Principal;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;

import javax.security.auth.x500.X500Principal;

/**
 * Handles selection of client certificate on the Java side. This class is responsible for selection
 * of the client certificate to be used for authentication and retrieval of the private key and full
 * certificate chain.
 *
 * The entry point is selectClientCertificate() and it will be called on the UI thread. Then the
 * class will construct and run an appropriate CertAsyncTask, that will run in background, and
 * finally pass the results back to the UI thread, which will return to the native code.
 */
@JNINamespace("chrome::android")
public class SSLClientCertificateRequest {
    static final String TAG = "SSLClientCertificateRequest";

    private static final DefaultAndroidKeyStore sLocalKeyStore =
            new DefaultAndroidKeyStore();

    /**
     * Common implementation for anynchronous task of handling the certificate request. This
     * AsyncTask uses the abstract methods to retrieve the authentication material from a
     * generalized key store. The key store is accessed in background, as the APIs being exercised
     * may be blocking. The results are posted back to native on the UI thread.
     */
    abstract static class CertAsyncTask extends AsyncTask<Void, Void, Void> {
        // These fields will store the results computed in doInBackground so that they can be posted
        // back in onPostExecute.
        private byte[][] mEncodedChain;
        private AndroidPrivateKey mAndroidPrivateKey;

        // Pointer to the native certificate request needed to return the results.
        private final long mNativePtr;

        CertAsyncTask(long nativePtr) {
            mNativePtr = nativePtr;
        }

        // These overriden methods will be used to access the key store.
        abstract String getAlias();
        abstract AndroidPrivateKey getPrivateKey(String alias);
        abstract X509Certificate[] getCertificateChain(String alias);

        @Override
        protected Void doInBackground(Void... params) {
            String alias = getAlias();
            if (alias == null) return null;

            AndroidPrivateKey key = getPrivateKey(alias);
            X509Certificate[] chain = getCertificateChain(alias);

            if (key == null || chain == null || chain.length == 0) {
                Log.w(TAG, "Empty client certificate chain?");
                return null;
            }

            // Encode the certificate chain.
            byte[][] encodedChain = new byte[chain.length][];
            try {
                for (int i = 0; i < chain.length; ++i) {
                    encodedChain[i] = chain[i].getEncoded();
                }
            } catch (CertificateEncodingException e) {
                Log.w(TAG, "Could not retrieve encoded certificate chain: " + e);
                return null;
            }

            mEncodedChain = encodedChain;
            mAndroidPrivateKey = key;
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            ThreadUtils.assertOnUiThread();
            nativeOnSystemRequestCompletion(mNativePtr, mEncodedChain, mAndroidPrivateKey);
        }
    }

    /** Implementation of CertAsyncTask for the system KeyChain API. */
    private static class CertAsyncTaskKeyChain extends CertAsyncTask {
        final Context mContext;
        final String mAlias;

        CertAsyncTaskKeyChain(Context context, long nativePtr, String alias) {
            super(nativePtr);
            mContext = context;
            assert alias != null;
            mAlias = alias;
        }

        @Override
        String getAlias() {
            return mAlias;
        }

        @Override
        AndroidPrivateKey getPrivateKey(String alias) {
            try {
                return sLocalKeyStore.createKey(KeyChain.getPrivateKey(mContext, alias));
            } catch (KeyChainException e) {
                Log.w(TAG, "KeyChainException when looking for '" + alias + "' certificate");
                return null;
            } catch (InterruptedException e) {
                Log.w(TAG, "InterruptedException when looking for '" + alias + "'certificate");
                return null;
            }
        }

        @Override
        X509Certificate[] getCertificateChain(String alias) {
            try {
                return KeyChain.getCertificateChain(mContext, alias);
            } catch (KeyChainException e) {
                Log.w(TAG, "KeyChainException when looking for '" + alias + "' certificate");
                return null;
            } catch (InterruptedException e) {
                Log.w(TAG, "InterruptedException when looking for '" + alias + "'certificate");
                return null;
            }
        }
    }

    /** Implementation of CertAsyncTask for use with a PKCS11-backed KeyStore. */
    private static class CertAsyncTaskPKCS11 extends CertAsyncTask {
        private final PKCS11AuthenticationManager mPKCS11AuthManager;
        private final String mHostName;
        private final int mPort;

        CertAsyncTaskPKCS11(long nativePtr, String hostName, int port,
                PKCS11AuthenticationManager pkcs11CardAuthManager) {
            super(nativePtr);
            mHostName = hostName;
            mPort = port;
            mPKCS11AuthManager = pkcs11CardAuthManager;
        }

        @Override
        String getAlias() {
            return mPKCS11AuthManager.getClientCertificateAlias(mHostName, mPort);
        }

        @Override
        AndroidPrivateKey getPrivateKey(String alias) {
            return mPKCS11AuthManager.getPrivateKey(alias);
        }

        @Override
        X509Certificate[] getCertificateChain(String alias) {
            return mPKCS11AuthManager.getCertificateChain(alias);
        }
    }

    /**
     * The system KeyChain API will call us back on the alias() method, passing the alias of the
     * certificate selected by the user.
     */
    private static class KeyChainCertSelectionCallback implements KeyChainAliasCallback {
        private final long mNativePtr;
        private final Context mContext;

        KeyChainCertSelectionCallback(Context context, long nativePtr) {
            mContext = context;
            mNativePtr = nativePtr;
        }

        @Override
        public void alias(final String alias) {
            // This is called by KeyChainActivity in a background thread. Post task to
            // handle the certificate selection on the UI thread.
            ThreadUtils.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (alias == null) {
                        // No certificate was selected.
                        ThreadUtils.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                nativeOnSystemRequestCompletion(mNativePtr, null, null);
                            }
                        });
                    } else {
                        new CertAsyncTaskKeyChain(mContext, mNativePtr, alias).execute();
                    }
                }
            });
        }
    }

    /**
     * Create a new asynchronous request to select a client certificate.
     *
     * @param nativePtr         The native object responsible for this request.
     * @param window            A WindowAndroid instance.
     * @param keyTypes          The list of supported key exchange types.
     * @param encodedPrincipals The list of CA DistinguishedNames.
     * @param hostName          The server host name is available (empty otherwise).
     * @param port              The server port if available (0 otherwise).
     * @return                  true on success.
     * Note that nativeOnSystemRequestComplete will be called iff this method returns true.
     */
    @CalledByNative
    private static boolean selectClientCertificate(final long nativePtr, final WindowAndroid window,
            final String[] keyTypes, byte[][] encodedPrincipals, final String hostName,
            final int port) {
        ThreadUtils.assertOnUiThread();

        final Activity activity = window.getActivity().get();
        if (activity == null) {
            Log.w(TAG, "Certificate request on GC'd activity.");
            return false;
        }

        // Build the list of principals from encoded versions.
        Principal[] principals = null;
        if (encodedPrincipals.length > 0) {
            principals = new X500Principal[encodedPrincipals.length];
            try {
                for (int n = 0; n < encodedPrincipals.length; n++) {
                    principals[n] = new X500Principal(encodedPrincipals[n]);
                }
            } catch (Exception e) {
                Log.w(TAG, "Exception while decoding issuers list: " + e);
                return false;
            }
        }

        final Principal[] principalsForCallback = principals;
        // Certificate for client authentication can be obtained either from the system store of
        // from a smart card (if available).
        Runnable useSystemStore = new Runnable() {
            @Override
            public void run() {
                KeyChainCertSelectionCallback callback =
                        new KeyChainCertSelectionCallback(activity.getApplicationContext(),
                            nativePtr);
                KeyChain.choosePrivateKeyAlias(activity, callback, keyTypes, principalsForCallback,
                    hostName, port, null);
            }
        };

        final Context appContext = activity.getApplicationContext();
        final PKCS11AuthenticationManager smartCardAuthManager =
            ((ChromiumApplication) appContext).getPKCS11AuthenticationManager();
        if (smartCardAuthManager.isPKCS11AuthEnabled()) {
            // Smart card support is available, prompt the user whether to use it or Android system
            // store.
            Runnable useSmartCard = new Runnable() {
                @Override
                public void run() {
                    new CertAsyncTaskPKCS11(nativePtr, hostName, port,
                            smartCardAuthManager).execute();
                }
            };
            Runnable cancelRunnable = new Runnable() {
                @Override
                public void run() {
                    // We took ownership of the request, need to delete it.
                    nativeOnSystemRequestCompletion(nativePtr, null, null);
                }
            };

            KeyStoreSelectionDialog selectionDialog = new KeyStoreSelectionDialog(
                    useSystemStore, useSmartCard, cancelRunnable);
            selectionDialog.show(activity.getFragmentManager(), null);
        } else {
            // Smart card support is not available, use the system store unconditionally.
            useSystemStore.run();
        }

        // We've taken ownership of the native ssl request object.
        return true;
    }

    public static void notifyClientCertificatesChangedOnIOThread() {
        Log.d(TAG, "ClientCertificatesChanged!");
        nativeNotifyClientCertificatesChangedOnIOThread();
    }

    private static native void nativeNotifyClientCertificatesChangedOnIOThread();

    // Called to pass request results to native side.
    private static native void nativeOnSystemRequestCompletion(
            long requestPtr, byte[][] certChain, AndroidPrivateKey androidKey);
}
