/*
 * Copyright 2018 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 android.security;

import android.annotation.NonNull;
import android.content.ContentResolver;
import android.content.Context;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
import android.util.Log;

import java.util.Locale;
import java.util.concurrent.Executor;

/**
 * Class used for displaying confirmation prompts.
 *
 * <p>Confirmation prompts are prompts shown to the user to confirm a given text and are
 * implemented in a way that a positive response indicates with high confidence that the user has
 * seen the given text, even if the Android framework (including the kernel) was
 * compromised. Implementing confirmation prompts with these guarantees requires dedicated
 * hardware-support and may not always be available.
 *
 * <p>Confirmation prompts are typically used with an external entitity - the <i>Relying Party</i> -
 * in the following way. The setup steps are as follows:
 * <ul>
 * <li> Before first use, the application generates a key-pair with the
 * {@link android.security.keystore.KeyGenParameterSpec.Builder#setUserConfirmationRequired
 * CONFIRMATION tag} set. Device attestation,
 * e.g. {@link java.security.KeyStore#getCertificateChain getCertificateChain()}, is used to
 * generate a certificate chain that includes the public key (<code>Kpub</code> in the following)
 * of the newly generated key.
 * <li> The application sends <code>Kpub</code> and the certificate chain resulting from device
 * attestation to the <i>Relying Party</i>.
 * <li> The <i>Relying Party</i> validates the certificate chain which involves checking the root
 * certificate is what is expected (e.g. a certificate from Google), each certificate signs the
 * next one in the chain, ending with <code>Kpub</code>, and that the attestation certificate
 * asserts that <code>Kpub</code> has the
 * {@link android.security.keystore.KeyGenParameterSpec.Builder#setUserConfirmationRequired
 * CONFIRMATION tag} set.
 * Additionally the relying party stores <code>Kpub</code> and associates it with the device
 * it was received from.
 * </ul>
 *
 * <p>The <i>Relying Party</i> is typically an external device (for example connected via
 * Bluetooth) or application server.
 *
 * <p>Before executing a transaction which requires a high assurance of user content, the
 * application does the following:
 * <ul>
 * <li> The application gets a cryptographic nonce from the <i>Relying Party</i> and passes this as
 * the <code>extraData</code> (via the Builder helper class) to the
 * {@link #presentPrompt presentPrompt()} method. The <i>Relying Party</i> stores the nonce locally
 * since it'll use it in a later step.
 * <li> If the user approves the prompt a <i>Confirmation Response</i> is returned in the
 * {@link ConfirmationCallback#onConfirmed onConfirmed(byte[])} callback as the
 * <code>dataThatWasConfirmed</code> parameter. This blob contains the text that was shown to the
 * user, the <code>extraData</code> parameter, and possibly other data.
 * <li> The application signs the <i>Confirmation Response</i> with the previously created key and
 * sends the blob and the signature to the <i>Relying Party</i>.
 * <li> The <i>Relying Party</i> checks that the signature was made with <code>Kpub</code> and then
 * extracts <code>promptText</code> matches what is expected and <code>extraData</code> matches the
 * previously created nonce. If all checks passes, the transaction is executed.
 * </ul>
 *
 * <p>A common way of implementing the "<code>promptText</code> is what is expected" check in the
 * last bullet, is to have the <i>Relying Party</i> generate <code>promptText</code> and store it
 * along the nonce in the <code>extraData</code> blob.
 */
public class ConfirmationPrompt {
    private static final String TAG = "ConfirmationPrompt";

    private CharSequence mPromptText;
    private byte[] mExtraData;
    private ConfirmationCallback mCallback;
    private Executor mExecutor;
    private Context mContext;

    private final KeyStore mKeyStore = KeyStore.getInstance();

    private void doCallback(int responseCode, byte[] dataThatWasConfirmed,
            ConfirmationCallback callback) {
        switch (responseCode) {
            case KeyStore.CONFIRMATIONUI_OK:
                callback.onConfirmed(dataThatWasConfirmed);
                break;

            case KeyStore.CONFIRMATIONUI_CANCELED:
                callback.onDismissed();
                break;

            case KeyStore.CONFIRMATIONUI_ABORTED:
                callback.onCanceled();
                break;

            case KeyStore.CONFIRMATIONUI_SYSTEM_ERROR:
                callback.onError(new Exception("System error returned by ConfirmationUI."));
                break;

            default:
                callback.onError(new Exception("Unexpected responseCode=" + responseCode
                                + " from onConfirmtionPromptCompleted() callback."));
                break;
        }
    }

    private final android.os.IBinder mCallbackBinder =
            new android.security.IConfirmationPromptCallback.Stub() {
                @Override
                public void onConfirmationPromptCompleted(
                        int responseCode, final byte[] dataThatWasConfirmed)
                        throws android.os.RemoteException {
                    if (mCallback != null) {
                        ConfirmationCallback callback = mCallback;
                        Executor executor = mExecutor;
                        mCallback = null;
                        mExecutor = null;
                        if (executor == null) {
                            doCallback(responseCode, dataThatWasConfirmed, callback);
                        } else {
                            executor.execute(new Runnable() {
                                    @Override
                                    public void run() {
                                        doCallback(responseCode, dataThatWasConfirmed, callback);
                                    }
                                });
                        }
                    }
                }
            };

    /**
     * A builder that collects arguments, to be shown on the system-provided confirmation prompt.
     */
    public static final class Builder {

        private Context mContext;
        private CharSequence mPromptText;
        private byte[] mExtraData;

        /**
         * Creates a builder for the confirmation prompt.
         *
         * @param context the application context
         */
        public Builder(Context context) {
            mContext = context;
        }

        /**
         * Sets the prompt text for the prompt.
         *
         * @param promptText the text to present in the prompt.
         * @return the builder.
         */
        public Builder setPromptText(CharSequence promptText) {
            mPromptText = promptText;
            return this;
        }

        /**
         * Sets the extra data for the prompt.
         *
         * @param extraData data to include in the response data.
         * @return the builder.
         */
        public Builder setExtraData(byte[] extraData) {
            mExtraData = extraData;
            return this;
        }

        /**
         * Creates a {@link ConfirmationPrompt} with the arguments supplied to this builder.
         *
         * @return a {@link ConfirmationPrompt}
         * @throws IllegalArgumentException if any of the required fields are not set.
         */
        public ConfirmationPrompt build() {
            if (TextUtils.isEmpty(mPromptText)) {
                throw new IllegalArgumentException("prompt text must be set and non-empty");
            }
            if (mExtraData == null) {
                throw new IllegalArgumentException("extraData must be set");
            }
            return new ConfirmationPrompt(mContext, mPromptText, mExtraData);
        }
    }

    private ConfirmationPrompt(Context context, CharSequence promptText, byte[] extraData) {
        mContext = context;
        mPromptText = promptText;
        mExtraData = extraData;
    }

    private static final int UI_OPTION_ACCESSIBILITY_INVERTED_FLAG = 1 << 0;
    private static final int UI_OPTION_ACCESSIBILITY_MAGNIFIED_FLAG = 1 << 1;

    private int getUiOptionsAsFlags() {
        int uiOptionsAsFlags = 0;
        ContentResolver contentResolver = mContext.getContentResolver();
        int inversionEnabled = Settings.Secure.getInt(contentResolver,
                Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0);
        if (inversionEnabled == 1) {
            uiOptionsAsFlags |= UI_OPTION_ACCESSIBILITY_INVERTED_FLAG;
        }
        float fontScale = Settings.System.getFloat(contentResolver,
                Settings.System.FONT_SCALE, (float) 1.0);
        if (fontScale > 1.0) {
            uiOptionsAsFlags |= UI_OPTION_ACCESSIBILITY_MAGNIFIED_FLAG;
        }
        return uiOptionsAsFlags;
    }

    private static boolean isAccessibilityServiceRunning(Context context) {
        boolean serviceRunning = false;
        try {
            ContentResolver contentResolver = context.getContentResolver();
            int a11yEnabled = Settings.Secure.getInt(contentResolver,
                    Settings.Secure.ACCESSIBILITY_ENABLED);
            if (a11yEnabled == 1) {
                serviceRunning = true;
            }
        } catch (SettingNotFoundException e) {
            Log.w(TAG, "Unexpected SettingNotFoundException");
            e.printStackTrace();
        }
        return serviceRunning;
    }

    /**
     * Requests a confirmation prompt to be presented to the user.
     *
     * When the prompt is no longer being presented, one of the methods in
     * {@link ConfirmationCallback} is called on the supplied callback object.
     *
     * Confirmation prompts may not be available when accessibility services are running so this
     * may fail with a {@link ConfirmationNotAvailableException} exception even if
     * {@link #isSupported} returns {@code true}.
     *
     * @param executor the executor identifying the thread that will receive the callback.
     * @param callback the callback to use when the prompt is done showing.
     * @throws IllegalArgumentException if the prompt text is too long or malfomed.
     * @throws ConfirmationAlreadyPresentingException if another prompt is being presented.
     * @throws ConfirmationNotAvailableException if confirmation prompts are not supported.
     */
    public void presentPrompt(@NonNull Executor executor, @NonNull ConfirmationCallback callback)
            throws ConfirmationAlreadyPresentingException,
            ConfirmationNotAvailableException {
        if (mCallback != null) {
            throw new ConfirmationAlreadyPresentingException();
        }
        if (isAccessibilityServiceRunning(mContext)) {
            throw new ConfirmationNotAvailableException();
        }
        mCallback = callback;
        mExecutor = executor;

        int uiOptionsAsFlags = getUiOptionsAsFlags();
        String locale = Locale.getDefault().toLanguageTag();
        int responseCode = mKeyStore.presentConfirmationPrompt(
                mCallbackBinder, mPromptText.toString(), mExtraData, locale, uiOptionsAsFlags);
        switch (responseCode) {
            case KeyStore.CONFIRMATIONUI_OK:
                return;

            case KeyStore.CONFIRMATIONUI_OPERATION_PENDING:
                throw new ConfirmationAlreadyPresentingException();

            case KeyStore.CONFIRMATIONUI_UNIMPLEMENTED:
                throw new ConfirmationNotAvailableException();

            case KeyStore.CONFIRMATIONUI_UIERROR:
                throw new IllegalArgumentException();

            default:
                // Unexpected error code.
                Log.w(TAG,
                        "Unexpected responseCode=" + responseCode
                        + " from presentConfirmationPrompt() call.");
                throw new IllegalArgumentException();
        }
    }

    /**
     * Cancels a prompt currently being displayed.
     *
     * On success, the
     * {@link ConfirmationCallback#onCanceled onCanceled()} method on
     * the supplied callback object will be called asynchronously.
     *
     * @throws IllegalStateException if no prompt is currently being presented.
     */
    public void cancelPrompt() {
        int responseCode = mKeyStore.cancelConfirmationPrompt(mCallbackBinder);
        if (responseCode == KeyStore.CONFIRMATIONUI_OK) {
            return;
        } else if (responseCode == KeyStore.CONFIRMATIONUI_OPERATION_PENDING) {
            throw new IllegalStateException();
        } else {
            // Unexpected error code.
            Log.w(TAG,
                    "Unexpected responseCode=" + responseCode
                    + " from cancelConfirmationPrompt() call.");
            throw new IllegalStateException();
        }
    }

    /**
     * Checks if the device supports confirmation prompts.
     *
     * @param context the application context.
     * @return true if confirmation prompts are supported by the device.
     */
    public static boolean isSupported(Context context) {
        if (isAccessibilityServiceRunning(context)) {
            return false;
        }
        return KeyStore.getInstance().isConfirmationPromptSupported();
    }
}
