/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.cts.verifier.security;

import android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings;
import android.security.KeyChain;
import android.security.KeyChainAliasCallback;
import android.security.KeyChainException;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;

import com.google.mockwebserver.MockResponse;
import com.google.mockwebserver.MockWebServer;

import java.io.InputStream;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.net.Socket;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.List;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509ExtendedKeyManager;

import libcore.java.security.TestKeyStore;
import libcore.javax.net.ssl.TestSSLContext;

import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;

/**
 * Simple activity based test that exercises the KeyChain API
 */
public class KeyChainTest extends PassFailButtons.Activity implements View.OnClickListener {

    private static final String TAG = "KeyChainTest";

    private static final int REQUEST_CA_INSTALL = 1;

    private TextView mInstructionView;
    private TextView mLogView;
    private Button mResetButton;
    private Button mSkipButton;
    private Button mNextButton;

    private List<Step> mSteps;
    int mCurrentStep;

    private KeyStore mKeyStore;
    private static final char[] KEYSTORE_PASSWORD = "".toCharArray();

    // How long to wait before giving up on the user selecting a key alias.
    private static final int KEYCHAIN_ALIAS_TIMEOUT_MS = (int) TimeUnit.MINUTES.toMillis(5L);

    @Override public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        View root = getLayoutInflater().inflate(R.layout.keychain_main, null);
        setContentView(root);

        setInfoResources(R.string.keychain_test, R.string.keychain_info, -1);
        setPassFailButtonClickListeners();

        mInstructionView = (TextView) root.findViewById(R.id.test_instruction);
        mLogView = (TextView) root.findViewById(R.id.test_log);
        mLogView.setMovementMethod(new ScrollingMovementMethod());

        mNextButton = (Button) root.findViewById(R.id.action_next);
        mNextButton.setOnClickListener(this);

        mResetButton = (Button) root.findViewById(R.id.action_reset);
        mResetButton.setOnClickListener(this);

        mSkipButton = (Button) root.findViewById(R.id.action_skip);
        mSkipButton.setOnClickListener(this);

        resetProgress();
    }

    @Override
    public void onClick(View v) {
        Step step = mSteps.get(mCurrentStep);
        if (v == mNextButton) {
            switch (step.task.getStatus()) {
                case PENDING: {
                    step.task.execute();
                    break;
                }
                case FINISHED: {
                    if (mCurrentStep + 1 < mSteps.size()) {
                        mCurrentStep += 1;
                        updateUi();
                    } else {
                        mSkipButton.setVisibility(View.INVISIBLE);
                        mNextButton.setVisibility(View.INVISIBLE);
                    }
                    break;
                }
            }
        } else if (v == mSkipButton) {
            step.task.cancel(false);
            mCurrentStep += 1;
            updateUi();
        } else if (v == mResetButton) {
            resetProgress();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case REQUEST_CA_INSTALL: {
                if (resultCode == RESULT_OK) {
                    log("CA Certificate installed successfully");
                } else {
                    log("REQUEST_CA_INSTALL failed with result code: " + resultCode);
                }
                break;
            }
            default:
                throw new IllegalStateException("requestCode == " + requestCode);
        }
    }

    private void resetProgress() {
        getPassButton().setEnabled(false);
        mLogView.setText("");

        mSteps = new ArrayList<>();
        mSteps.add(new Step(R.string.keychain_setup_desc, false, new SetupTestKeyStoreTask()));
        mSteps.add(new Step(R.string.keychain_install_desc, true, new InstallCredentialsTask()));
        mSteps.add(new Step(R.string.keychain_https_desc, false, new TestHttpsRequestTask()));
        mSteps.add(new Step(R.string.keychain_reset_desc, true, new ClearCredentialsTask()));
        mCurrentStep = 0;

        updateUi();
    }

    private void updateUi() {
        mLogView.setText("");

        if (mCurrentStep >= mSteps.size()) {
            mSkipButton.setVisibility(View.INVISIBLE);
            mNextButton.setVisibility(View.INVISIBLE);
            getPassButton().setEnabled(true);
            return;
        }

        final Step step = mSteps.get(mCurrentStep);
        if (step.task.getStatus() == AsyncTask.Status.PENDING) {
            mInstructionView.setText(step.instructionTextId);
        }
        mSkipButton.setVisibility(step.skippable ? View.VISIBLE : View.INVISIBLE);
        mNextButton.setVisibility(View.VISIBLE);
    }

    private class SetupTestKeyStoreTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            final Certificate[] chain = new Certificate[2];
            final Key privKey;

            log("Reading resources");
            Resources res = getResources();
            ByteArrayOutputStream userKey = new ByteArrayOutputStream();
            try {
                InputStream is = res.openRawResource(R.raw.userkey);
                byte[] buffer = new byte[4096];
                for (int n; (n = is.read(buffer, 0, buffer.length)) != -1;) {
                    userKey.write(buffer, 0, n);
                }
            } catch (IOException e) {
                Log.e(TAG, "Reading private key failed", e);
                return null;
            }
            log("Private key length: " + userKey.size() + " bytes");

            log("Setting up KeyStore");
            try {
                KeyFactory keyFact = KeyFactory.getInstance("RSA");
                privKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(userKey.toByteArray()));

                final CertificateFactory f = CertificateFactory.getInstance("X.509");
                chain[0] = f.generateCertificate(res.openRawResource(R.raw.usercert));
                chain[1] = f.generateCertificate(res.openRawResource(R.raw.cacert));
            } catch (GeneralSecurityException gse) {
                Log.w(TAG, "Certificate generation failed", gse);
                return null;
            }

            try {
                // Create a PKCS12 keystore populated with key + certificate chain
                KeyStore ks = KeyStore.getInstance("PKCS12");
                ks.load(null, null);
                ks.setKeyEntry("alias", privKey, KEYSTORE_PASSWORD, chain);
                mKeyStore = ks;
                log("KeyStore initialized");
            } catch (Exception e) {
                log("KeyStore initialization failed");
                Log.e(TAG, "", e);
            }
            return null;
        }
    }

    private class InstallCredentialsTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            try {
                Intent intent = KeyChain.createInstallIntent();
                intent.putExtra(KeyChain.EXTRA_NAME, TAG);

                // Write keystore to byte array for installation
                ByteArrayOutputStream pkcs12 = new ByteArrayOutputStream();
                mKeyStore.store(pkcs12, KEYSTORE_PASSWORD);
                if (pkcs12.size() == 0) {
                    throw new AssertionError("Credential archive is empty");
                }
                log("Requesting install of server's credentials");
                intent.putExtra(KeyChain.EXTRA_PKCS12, pkcs12.toByteArray());
                startActivityForResult(intent, REQUEST_CA_INSTALL);
            } catch (Exception e) {
                log("Failed to install credentials: " + e);
            }
            return null;
        }
    }

    private class TestHttpsRequestTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            try {
                URL url = startWebServer();
                makeHttpsRequest(url);
            } catch (Exception e) {
                Log.e(TAG, "HTTPS request unsuccessful", e);
                log("Connection failed");
                return null;
            }

            runOnUiThread(new Runnable() {
                @Override public void run() {
                    getPassButton().setEnabled(true);
                }
            });
            return null;
        }

        /**
         * Create a mock web server.
         * The server authenticates itself to the client using the key pair and certificate from the
         * PKCS#12 keystore used in this test. Client authentication uses default trust management:
         * the server trusts only the certificates installed in the credential storage of this
         * user/profile.
         */
        private URL startWebServer() throws Exception {
            log("Starting web server");
            String kmfAlgoritm = KeyManagerFactory.getDefaultAlgorithm();
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfAlgoritm);
            kmf.init(mKeyStore, KEYSTORE_PASSWORD);
            SSLContext serverContext = SSLContext.getInstance("TLS");
            serverContext.init(kmf.getKeyManagers(),
                    null /* TrustManager[] */,
                    null /* SecureRandom */);
            SSLSocketFactory sf = serverContext.getSocketFactory();
            SSLSocketFactory needsClientAuth = TestSSLContext.clientAuth(sf,
                    false /* Want client auth */,
                    true /* Need client auth */);
            MockWebServer server = new MockWebServer();
            server.useHttps(needsClientAuth, false /* tunnelProxy */);
            server.enqueue(new MockResponse().setBody("this response comes via HTTPS"));
            server.play();
            return server.getUrl("/");
        }

        /**
         * Open a new connection to the server.
         * The client authenticates itself to the server using a private key and certificate
         * supplied by KeyChain. Server authentication uses default trust management: the client
         * trusts only certificates installed in the credential storage of this user/profile. This
         * setup is expected to work because the server uses a private key whose certificate was
         * installed earlier during this test.
         */
        private void makeHttpsRequest(URL url) throws Exception {
            log("Making https request to " + url);
            SSLContext clientContext = SSLContext.getInstance("TLS");
            clientContext.init(new KeyManager[] { new KeyChainKeyManager() },
                    null /* TrustManager[] */,
                    null /* SecureRandom */);
            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
            connection.setSSLSocketFactory(clientContext.getSocketFactory());
            if (connection.getResponseCode() != 200) {
                log("Connection failed. Response code: " + connection.getResponseCode());
                throw new AssertionError();
            }
            log("Connection succeeded.");
        }
    }

    private class ClearCredentialsTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            final Intent securitySettingsIntent = new Intent(Settings.ACTION_SECURITY_SETTINGS);
            startActivity(securitySettingsIntent);
            log("Started action: " + Settings.ACTION_SECURITY_SETTINGS);
            log("All tests complete!");
            return null;
        }
    }

    /**
     * Key manager which synchronously prompts for its aliases via KeyChain
     */
    private class KeyChainKeyManager extends X509ExtendedKeyManager {
        @Override
        public String chooseClientAlias(String[] keyTypes, Principal[] issuers, Socket socket) {
            log("KeyChainKeyManager chooseClientAlias");
            KeyChainAliasCallback aliasCallback = Mockito.mock(KeyChainAliasCallback.class);
            KeyChain.choosePrivateKeyAlias(KeyChainTest.this, aliasCallback,
                                           keyTypes, issuers,
                                           socket.getInetAddress().getHostName(), socket.getPort(),
                                           null);

            ArgumentCaptor<String> aliasCaptor = ArgumentCaptor.forClass(String.class);
            Mockito.verify(aliasCallback, Mockito.timeout((int) KEYCHAIN_ALIAS_TIMEOUT_MS))
                    .alias(aliasCaptor.capture());

            log("Certificate alias: \"" + aliasCaptor.getValue() + "\"");
            return aliasCaptor.getValue();
        }

        @Override
        public String chooseServerAlias(String keyType,
                                                  Principal[] issuers,
                                                  Socket socket) {
            // Not a client SSLSocket callback
            throw new UnsupportedOperationException();
        }

        @Override
        public X509Certificate[] getCertificateChain(String alias) {
            try {
                log("KeyChainKeyManager getCertificateChain");
                X509Certificate[] certificateChain =
                        KeyChain.getCertificateChain(KeyChainTest.this, alias);
                if (certificateChain == null) {
                    log("Null certificate chain!");
                    return null;
                }
                log("Returned " + certificateChain.length + " certificates in chain");
                for (int i = 0; i < certificateChain.length; i++) {
                    Log.d(TAG, "certificate[" + i + "]=" + certificateChain[i]);
                }
                return certificateChain;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return null;
            } catch (KeyChainException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public String[] getClientAliases(String keyType, Principal[] issuers) {
            // not a client SSLSocket callback
            throw new UnsupportedOperationException();
        }

        @Override
        public String[] getServerAliases(String keyType, Principal[] issuers) {
            // not a client SSLSocket callback
            throw new UnsupportedOperationException();
        }

        @Override
        public PrivateKey getPrivateKey(String alias) {
            try {
                log("KeyChainKeyManager.getPrivateKey(\"" + alias + "\")");
                PrivateKey privateKey = KeyChain.getPrivateKey(KeyChainTest.this, alias);
                Log.d(TAG, "privateKey = " + privateKey);
                return privateKey;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return null;
            } catch (KeyChainException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * Write a message to the log, also to a visible TextView if available.
     */
    private void log(final String message) {
        Log.d(TAG, message);
        if (mLogView != null) {
            runOnUiThread(new Runnable() {
                @Override public void run() {
                    mLogView.append(message + "\n");
                }
            });
        }
    }

    /**
     * Utility class to store one step per object.
     */
    private static class Step {
        // Instruction message to show before running
        int instructionTextId;

        // Whether to allow a 'skip' button for this step
        boolean skippable;

        // Set of commands to run when 'next' is pressed
        AsyncTask<Void, Void, Void> task;

        public Step(int instructionTextId, boolean skippable, AsyncTask<Void, Void, Void> task) {
            this.instructionTextId = instructionTextId;
            this.skippable = skippable;
            this.task = task;
        }
    }
}
