/*
 * Copyright (C) 2009 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.certinstaller;

import static android.security.KeyStore.UID_SELF;

import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.security.Credentials;
import android.security.IKeyChainService;
import android.security.KeyChain;
import android.text.Html;
import android.text.TextUtils;
import android.util.Log;

import com.android.org.bouncycastle.asn1.ASN1InputStream;
import com.android.org.bouncycastle.asn1.ASN1Sequence;
import com.android.org.bouncycastle.asn1.DEROctetString;
import com.android.org.bouncycastle.asn1.x509.BasicConstraints;
import com.android.org.conscrypt.TrustedCertificateStore;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStore.PasswordProtection;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;

/**
 * A helper class for accessing the raw data in the intent extra and handling
 * certificates.
 */
class CredentialHelper {
    private static final String DATA_KEY = "data";
    private static final String CERTS_KEY = "crts";
    private static final String USER_KEY_ALGORITHM = "user_key_algorithm";
    private static final String SETTINGS_PACKAGE = "com.android.settings";

    private static final String TAG = "CredentialHelper";

    // keep raw data from intent's extra
    private HashMap<String, byte[]> mBundle = new HashMap<String, byte[]>();

    private String mName = "";
    private String mCertUsageSelected = "";
    private String mReferrer = "";
    private int mUid = -1;
    private PrivateKey mUserKey;
    private X509Certificate mUserCert;
    private List<X509Certificate> mCaCerts = new ArrayList<X509Certificate>();

    CredentialHelper() {
    }

    CredentialHelper(Intent intent) {
        Bundle bundle = intent.getExtras();
        if (bundle == null) {
            return;
        }

        String name = bundle.getString(KeyChain.EXTRA_NAME);
        bundle.remove(KeyChain.EXTRA_NAME);
        if (name != null) {
            mName = name;
        }

        String certUsageSelected = bundle.getString(Credentials.EXTRA_CERTIFICATE_USAGE);
        bundle.remove(Credentials.EXTRA_CERTIFICATE_USAGE);
        if (certUsageSelected != null) {
            setCertUsageSelectedAndUid(certUsageSelected);
        } else {
            mUid = bundle.getInt(Credentials.EXTRA_INSTALL_AS_UID, -1);
        }
        bundle.remove(Credentials.EXTRA_INSTALL_AS_UID);

        String referrer = bundle.getString(Intent.EXTRA_REFERRER);
        bundle.remove(Intent.EXTRA_REFERRER);
        if (referrer != null) {
            mReferrer = referrer;
        }

        Log.d(TAG, "# extras: " + bundle.size());
        for (String key : bundle.keySet()) {
            byte[] bytes = bundle.getByteArray(key);
            Log.d(TAG, "   " + key + ": " + ((bytes == null) ? -1 : bytes.length));
            mBundle.put(key, bytes);
        }
        parseCert(getData(KeyChain.EXTRA_CERTIFICATE));
    }

    synchronized void onSaveStates(Bundle outStates) {
        try {
            outStates.putSerializable(DATA_KEY, mBundle);
            outStates.putString(KeyChain.EXTRA_NAME, mName);
            outStates.putInt(Credentials.EXTRA_INSTALL_AS_UID, mUid);
            if (mUserKey != null) {
                Log.d(TAG, "Key algorithm: " + mUserKey.getAlgorithm());
                outStates.putString(USER_KEY_ALGORITHM, mUserKey.getAlgorithm());
                outStates.putByteArray(Credentials.USER_PRIVATE_KEY,
                        mUserKey.getEncoded());
            }
            ArrayList<byte[]> certs = new ArrayList<byte[]>(mCaCerts.size() + 1);
            if (mUserCert != null) {
                certs.add(mUserCert.getEncoded());
            }
            for (X509Certificate cert : mCaCerts) {
                certs.add(cert.getEncoded());
            }
            outStates.putByteArray(CERTS_KEY, Util.toBytes(certs));
        } catch (CertificateEncodingException e) {
            throw new AssertionError(e);
        }
    }

    void onRestoreStates(Bundle savedStates) {
        mBundle = (HashMap) savedStates.getSerializable(DATA_KEY);
        mName = savedStates.getString(KeyChain.EXTRA_NAME);
        mUid = savedStates.getInt(Credentials.EXTRA_INSTALL_AS_UID, -1);
        String userKeyAlgorithm = savedStates.getString(USER_KEY_ALGORITHM);
        byte[] userKeyBytes = savedStates.getByteArray(Credentials.USER_PRIVATE_KEY);
        Log.d(TAG, "Loaded key algorithm: " + userKeyAlgorithm);
        if (userKeyAlgorithm != null && userKeyBytes != null) {
            setPrivateKey(userKeyAlgorithm, userKeyBytes);
        }

        ArrayList<byte[]> certs = Util.fromBytes(savedStates.getByteArray(CERTS_KEY));
        for (byte[] cert : certs) {
            parseCert(cert);
        }
    }

    X509Certificate getUserCertificate() {
        return mUserCert;
    }

    private void parseCert(byte[] bytes) {
        if (bytes == null) {
            return;
        }

        try {
            CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
            X509Certificate cert = (X509Certificate)
                    certFactory.generateCertificate(
                            new ByteArrayInputStream(bytes));
            if (isCa(cert)) {
                Log.d(TAG, "got a CA cert");
                mCaCerts.add(cert);
            } else {
                Log.d(TAG, "got a user cert");
                mUserCert = cert;
            }
        } catch (CertificateException e) {
            Log.w(TAG, "parseCert(): " + e);
        }
    }

    private boolean isCa(X509Certificate cert) {
        try {
            // TODO: add a test about this
            byte[] asn1EncodedBytes = cert.getExtensionValue("2.5.29.19");
            if (asn1EncodedBytes == null) {
                return false;
            }
            DEROctetString derOctetString = (DEROctetString)
                    new ASN1InputStream(asn1EncodedBytes).readObject();
            byte[] octets = derOctetString.getOctets();
            ASN1Sequence sequence = (ASN1Sequence)
                    new ASN1InputStream(octets).readObject();
            return BasicConstraints.getInstance(sequence).isCA();
        } catch (IOException e) {
            return false;
        }
    }

    boolean hasPkcs12KeyStore() {
        return mBundle.containsKey(KeyChain.EXTRA_PKCS12);
    }

    boolean hasPrivateKey() {
        return mBundle.containsKey(Credentials.EXTRA_PRIVATE_KEY);
    }

    int getUidFromCertificateUsage(String certUsage) {
        if (Credentials.CERTIFICATE_USAGE_WIFI.equals(certUsage)) {
            return Process.WIFI_UID;
        } else {
            return UID_SELF;
        }
    }

    boolean hasUserCertificate() {
        return (mUserCert != null);
    }

    boolean hasCaCerts() {
        return !mCaCerts.isEmpty();
    }

    boolean hasAnyForSystemInstall() {
        return (mUserKey != null) || hasUserCertificate() || hasCaCerts();
    }

    void setPrivateKey(String algorithm, byte[] bytes) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
            mUserKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(bytes));
        } catch (NoSuchAlgorithmException e) {
            throw new AssertionError(e);
        } catch (InvalidKeySpecException e) {
            throw new AssertionError(e);
        }
    }

    boolean containsAnyRawData() {
        return !mBundle.isEmpty();
    }

    byte[] getData(String key) {
        return mBundle.get(key);
    }

    void putPkcs12Data(byte[] data) {
        mBundle.put(KeyChain.EXTRA_PKCS12, data);
    }

    CharSequence getDescription(Context context) {
        // TODO: create more descriptive string
        StringBuilder sb = new StringBuilder();
        String newline = "<br>";
        if (mUserKey != null) {
            sb.append(context.getString(R.string.one_userkey)).append(newline);
            sb.append(context.getString(R.string.userkey_type)).append(mUserKey.getAlgorithm())
                    .append(newline);
        }
        if (mUserCert != null) {
            sb.append(context.getString(R.string.one_usercrt)).append(newline);
        }
        int n = mCaCerts.size();
        if (n > 0) {
            if (n == 1) {
                sb.append(context.getString(R.string.one_cacrt));
            } else {
                sb.append(context.getString(R.string.n_cacrts, n));
            }
        }
        return Html.fromHtml(sb.toString());
    }

    void setName(String name) {
        mName = name;
    }

    String getName() {
        return mName;
    }

    void setCertUsageSelectedAndUid(String certUsageSelected) {
        mCertUsageSelected = certUsageSelected;
        mUid = getUidFromCertificateUsage(certUsageSelected);
    }

    String getCertUsageSelected() {
        return mCertUsageSelected;
    }

    boolean calledBySettings() {
        return mReferrer != null && mReferrer.equals(SETTINGS_PACKAGE);
    }

    Intent createSystemInstallIntent(final Context context) {
        Intent intent = new Intent("com.android.credentials.INSTALL");
        // To prevent the private key from being sniffed, we explicitly spell
        // out the intent receiver class.
        intent.setComponent(ComponentName.unflattenFromString(
                context.getString(R.string.config_system_install_component)));
        intent.putExtra(Credentials.EXTRA_INSTALL_AS_UID, mUid);
        intent.putExtra(Credentials.EXTRA_USER_KEY_ALIAS, mName);
        try {
            if (mUserKey != null) {
                intent.putExtra(Credentials.EXTRA_USER_PRIVATE_KEY_DATA,
                        mUserKey.getEncoded());
            }
            if (mUserCert != null) {
                intent.putExtra(Credentials.EXTRA_USER_CERTIFICATE_DATA,
                        Credentials.convertToPem(mUserCert));
            }
            if (!mCaCerts.isEmpty()) {
                X509Certificate[] caCerts
                        = mCaCerts.toArray(new X509Certificate[mCaCerts.size()]);
                intent.putExtra(Credentials.EXTRA_CA_CERTIFICATES_DATA,
                        Credentials.convertToPem(caCerts));
            }
            return intent;
        } catch (IOException e) {
            throw new AssertionError(e);
        } catch (CertificateEncodingException e) {
            throw new AssertionError(e);
        }
    }

    boolean installVpnAndAppsTrustAnchors(Context context, IKeyChainService keyChainService) {
        final TrustedCertificateStore trustedCertificateStore = new TrustedCertificateStore();
        for (X509Certificate caCert : mCaCerts) {
            byte[] bytes = null;
            try {
                bytes = caCert.getEncoded();
            } catch (CertificateEncodingException e) {
                throw new AssertionError(e);
            }
            if (bytes != null) {
                try {
                    keyChainService.installCaCertificate(bytes);
                } catch (RemoteException e) {
                    Log.w(TAG, "installCaCertsToKeyChain(): " + e);
                    return false;
                }

                String alias = trustedCertificateStore.getCertificateAlias(caCert);
                if (alias == null) {
                    Log.e(TAG, "alias is null");
                    return false;
                }

                maybeApproveCaCert(context, alias);
            }
        }
        return true;
    }

    private void maybeApproveCaCert(Context context, String alias) {
        final KeyguardManager keyguardManager = context.getSystemService(KeyguardManager.class);
        if (keyguardManager.isDeviceSecure(UserHandle.myUserId())) {
            // Since the cert is installed by real user, the cert is approved by the user
            final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
            dpm.approveCaCert(alias, UserHandle.myUserId(), true);
        }
    }

    boolean hasPassword() {
        if (!hasPkcs12KeyStore()) {
            return false;
        }
        try {
            return loadPkcs12Internal(new PasswordProtection(new char[] {})) == null;
        } catch (Exception e) {
            return true;
        }
    }

    boolean extractPkcs12(String password) {
        try {
            return extractPkcs12Internal(new PasswordProtection(password.toCharArray()));
        } catch (Exception e) {
            Log.w(TAG, "extractPkcs12(): " + e, e);
            return false;
        }
    }

    private boolean extractPkcs12Internal(PasswordProtection password)
            throws Exception {
        // TODO: add test about this
        java.security.KeyStore keystore = loadPkcs12Internal(password);

        Enumeration<String> aliases = keystore.aliases();
        if (!aliases.hasMoreElements()) {
            Log.e(TAG, "PKCS12 file has no elements");
            return false;
        }

        while (aliases.hasMoreElements()) {
            String alias = aliases.nextElement();
            if (keystore.isKeyEntry(alias)) {
                KeyStore.Entry entry = keystore.getEntry(alias, password);
                Log.d(TAG, "extracted alias = " + alias + ", entry=" + entry.getClass());

                if (entry instanceof PrivateKeyEntry) {
                    if (TextUtils.isEmpty(mName)) {
                        mName = alias;
                    }
                    return installFrom((PrivateKeyEntry) entry);
                }
            } else {
                // KeyStore.getEntry with non-null ProtectionParameter can only be invoked on
                // PrivateKeyEntry or SecretKeyEntry.
                // See https://docs.oracle.com/javase/8/docs/api/java/security/KeyStore.html
                Log.d(TAG, "Skip non-key entry, alias = " + alias);
            }
        }
        return true;
    }

    private java.security.KeyStore loadPkcs12Internal(PasswordProtection password)
            throws Exception {
        java.security.KeyStore keystore = java.security.KeyStore.getInstance("PKCS12");
        keystore.load(new ByteArrayInputStream(getData(KeyChain.EXTRA_PKCS12)),
                      password.getPassword());
        return keystore;
    }

    private synchronized boolean installFrom(PrivateKeyEntry entry) {
        mUserKey = entry.getPrivateKey();
        mUserCert = (X509Certificate) entry.getCertificate();

        Certificate[] certs = entry.getCertificateChain();
        Log.d(TAG, "# certs extracted = " + certs.length);
        mCaCerts = new ArrayList<X509Certificate>(certs.length);
        for (Certificate c : certs) {
            X509Certificate cert = (X509Certificate) c;
            if (isCa(cert)) {
                mCaCerts.add(cert);
            }
        }
        Log.d(TAG, "# ca certs extracted = " + mCaCerts.size());

        return true;
    }

    /**
     * Returns true if this credential contains _only_ CA certificates to be used as trust anchors
     * for VPN and apps.
     */
    public boolean hasOnlyVpnAndAppsTrustAnchors() {
        if (!hasCaCerts()) {
            return false;
        }
        if (mUid != UID_SELF) {
            // VPN and Apps trust anchors can only be installed under UID_SELF
            return false;
        }

        if (mUserKey != null) {
            // We are installing a key pair for client authentication, its CA
            // should have nothing to do with VPN and apps trust anchors.
            return false;
        } else {
            return true;
        }
    }

    public String getReferrer() {
        return mReferrer;
    }
}
