package com.android.cts.verifier.managedprovisioning;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.KeyguardManager;
import android.content.DialogInterface;
import android.content.Intent;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.CountDownTimer;
import android.provider.Settings;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.security.keystore.UserNotAuthenticatedException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;

import com.android.cts.verifier.ArrayTestListAdapter;
import com.android.cts.verifier.DialogTestListActivity;
import com.android.cts.verifier.R;
import com.android.cts.verifier.TestResult;

import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;

/**
 * Test device credential-bound keys in work profile.
 * Currently there are two types, one is keys bound to lockscreen passwords which can be configured
 * to remain available within a certain timeout after the latest successful user authentication.
 * The other is keys bound to fingerprint authentication which require explicit fingerprint
 * authentication before they can be accessed.
 */
public class AuthenticationBoundKeyTestActivity extends DialogTestListActivity {

    public static final String ACTION_AUTH_BOUND_KEY_TEST =
            "com.android.cts.verifier.managedprovisioning.action.AUTH_BOUND_KEY_TEST";

    private static final int AUTHENTICATION_DURATION_SECONDS = 5;
    private static final String LOCKSCREEN_KEY_NAME = "mp_lockscreen_key";
    private static final String FINGERPRINT_KEY_NAME = "mp_fingerprint_key";
    private static final byte[] SECRET_BYTE_ARRAY = new byte[] {1, 2, 3, 4, 5, 6};
    private static final int CONFIRM_CREDENTIALS_REQUEST_CODE = 1;
    private static final int FINGERPRINT_PERMISSION_REQUEST_CODE = 0;

    private static final int LOCKSCREEN = 1;
    private static final int FINGERPRINT = 2;

    private static final String KEYSTORE_NAME = "AndroidKeyStore";
    private static final String CIPHER_TRANSFORMATION =  KeyProperties.KEY_ALGORITHM_AES + "/"
            + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7;


    private KeyguardManager mKeyguardManager;
    private FingerprintManager mFingerprintManager;
    private boolean mFingerprintSupported;

    private DialogTestListItem mLockScreenBoundKeyTest;
    private DialogTestListItem mFingerprintBoundKeyTest;

    private Cipher mFingerprintCipher;

    public AuthenticationBoundKeyTestActivity() {
        super(R.layout.provisioning_byod,
                R.string.provisioning_byod_auth_bound_key,
                R.string.provisioning_byod_auth_bound_key_info,
                R.string.provisioning_byod_auth_bound_key_instruction);
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mKeyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
        mFingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
        mFingerprintSupported = mFingerprintManager != null
                && mFingerprintManager.isHardwareDetected();
        // Need to have valid mFingerprintSupported value before calling super.onCreate() because
        // mFingerprintSupported is used in setupTests() which gets called by super.onCreate().
        super.onCreate(savedInstanceState);

        mPrepareTestButton.setText(R.string.provisioning_byod_auth_bound_key_set_up);
        mPrepareTestButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                startActivity(new Intent(Settings.ACTION_SECURITY_SETTINGS));
            }
        });
        if (mFingerprintSupported) {
            requestPermissions(new String[] {Manifest.permission.USE_FINGERPRINT},
                    FINGERPRINT_PERMISSION_REQUEST_CODE);
        }
    }

    private class LockscreenCountDownTester extends CountDownTimer {

        private Toast mToast;

        public LockscreenCountDownTester() {
            // Wait for AUTHENTICATION_DURATION_SECONDS so the key is evicted before the real test.
            super(AUTHENTICATION_DURATION_SECONDS * 1000, 1000);
            mToast = Toast.makeText(AuthenticationBoundKeyTestActivity.this, "", Toast.LENGTH_SHORT);
        }

        @Override
        public void onFinish() {
            mToast.cancel();
            if (tryEncryptWithLockscreenKey()) {
                showToast("Test failed. Key accessible without auth.");
                setTestResult(mLockScreenBoundKeyTest, TestResult.TEST_RESULT_FAILED);
            } else {
                // Start the Confirm Credentials screen.
                Intent intent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null);
                if (intent != null) {
                    startActivityForResult(intent, CONFIRM_CREDENTIALS_REQUEST_CODE);
                } else {
                    showToast("Test failed. No lockscreen password exists.");
                    setTestResult(mLockScreenBoundKeyTest, TestResult.TEST_RESULT_FAILED);
                }
            }
        }

        @Override
        public void onTick(long millisUntilFinished) {
            mToast.setText(String.format("Lockscreen challenge start in %d seconds..",
                    millisUntilFinished / 1000));
            mToast.show();
        }
    }


    @Override
    protected void setupTests(ArrayTestListAdapter adapter) {
        mLockScreenBoundKeyTest = new DialogTestListItem(this,
                R.string.provisioning_byod_lockscreen_bound_key,
                "BYOD_LockScreenBoundKeyTest") {

            @Override
            public void performTest(DialogTestListActivity activity) {
                if (checkPreconditions()) {
                    createKey(LOCKSCREEN);
                    new LockscreenCountDownTester().start();
                }
            }
        };
        adapter.add(mLockScreenBoundKeyTest);

        if (mFingerprintSupported) {
            mFingerprintBoundKeyTest = new DialogTestListItem(this,
                    R.string.provisioning_byod_fingerprint_bound_key,
                    "BYOD_FingerprintBoundKeyTest") {

                @Override
                public void performTest(DialogTestListActivity activity) {
                    if (checkPreconditions()) {
                        createKey(FINGERPRINT);
                        mFingerprintCipher = initFingerprintEncryptionCipher();
                        if (tryEncryptWithFingerprintKey(mFingerprintCipher)) {
                            showToast("Test failed. Key accessible without auth.");
                            setTestResult(mFingerprintBoundKeyTest, TestResult.TEST_RESULT_FAILED);
                        } else {
                            new FingerprintAuthDialogFragment().show(getFragmentManager(),
                                    "fingerprint_dialog");
                        }
                    }
                }
            };
            adapter.add(mFingerprintBoundKeyTest);
        }
    }

    private boolean checkPreconditions() {
        if (!mKeyguardManager.isKeyguardSecure()) {
            showToast("Please set a lockscreen password.");
            return false;
        } else if (mFingerprintSupported && !mFingerprintManager.hasEnrolledFingerprints()) {
            showToast("Please enroll a fingerprint.");
            return false;
        } else {
            return true;
        }
    }

    private String getKeyName(int testType) {
        return testType == LOCKSCREEN ? LOCKSCREEN_KEY_NAME : FINGERPRINT_KEY_NAME;
    }
    /**
     * Creates a symmetric key in the Android Key Store which can only be used after the user has
     * authenticated with device credentials.
     */
    private void createKey(int testType) {
        try {
            // Set the alias of the entry in Android KeyStore where the key will appear
            // and the constrains (purposes) in the constructor of the Builder
            KeyGenParameterSpec.Builder builder;
            builder = new KeyGenParameterSpec.Builder(getKeyName(testType),
                    KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                    .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                    .setUserAuthenticationRequired(true)
                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7);
            if (testType == LOCKSCREEN) {
                // Require that the user unlocked the lockscreen in the last 5 seconds
                builder.setUserAuthenticationValidityDurationSeconds(
                        AUTHENTICATION_DURATION_SECONDS);
            }
            KeyGenerator keyGenerator = KeyGenerator.getInstance(
                    KeyProperties.KEY_ALGORITHM_AES, KEYSTORE_NAME);
            keyGenerator.init(builder.build());
            keyGenerator.generateKey();
        } catch (NoSuchAlgorithmException | NoSuchProviderException
                | InvalidAlgorithmParameterException e) {
            throw new RuntimeException("Failed to create a symmetric key", e);
        }
    }

    private SecretKey loadSecretKey(int testType) {
        try {
            KeyStore keyStore = KeyStore.getInstance(KEYSTORE_NAME);
            keyStore.load(null);
            return (SecretKey) keyStore.getKey(getKeyName(testType), null);
        } catch (UnrecoverableKeyException  | CertificateException |KeyStoreException | IOException
                | NoSuchAlgorithmException e) {
            throw new RuntimeException("Failed to load a symmetric key", e);
        }
    }

    private boolean tryEncryptWithLockscreenKey() {
        try {
            // Try encrypting something, it will only work if the user authenticated within
            // the last AUTHENTICATION_DURATION_SECONDS seconds.
            Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, loadSecretKey(LOCKSCREEN));
            cipher.doFinal(SECRET_BYTE_ARRAY);
            return true;
        } catch (UserNotAuthenticatedException e) {
            // User is not authenticated, let's authenticate with device credentials.
            return false;
        } catch (KeyPermanentlyInvalidatedException e) {
            // This happens if the lock screen has been disabled or reset after the key was
            // generated.
            createKey(LOCKSCREEN);
            showToast("Set up lockscreen after test ran. Retry the test.");
            return false;
        } catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException
                | NoSuchPaddingException | NoSuchAlgorithmException e) {
            throw new RuntimeException("Encrypt with lockscreen-bound key failed", e);
        }
    }

    private Cipher initFingerprintEncryptionCipher() {
        try {
            Cipher cipher =  Cipher.getInstance(CIPHER_TRANSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, loadSecretKey(FINGERPRINT));
            return cipher;
        } catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
            return null;
        } catch (KeyPermanentlyInvalidatedException e) {
            // This happens if the lock screen has been disabled or reset after the key was
            // generated after the key was generated.
            createKey(FINGERPRINT);
            showToast("Set up lockscreen after test ran. Retry the test.");
            return null;
        } catch (InvalidKeyException e) {
            throw new RuntimeException("Init cipher with fingerprint-bound key failed", e);
        }
    }

    private boolean tryEncryptWithFingerprintKey(Cipher cipher) {

        try {
            cipher.doFinal(SECRET_BYTE_ARRAY);
            return true;
        } catch (IllegalBlockSizeException e) {
            // Cannot encrypt, key is unavailable
            return false;
        } catch (BadPaddingException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected void handleActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case CONFIRM_CREDENTIALS_REQUEST_CODE:
                if (resultCode == RESULT_OK) {
                    if (tryEncryptWithLockscreenKey()) {
                        setTestResult(mLockScreenBoundKeyTest, TestResult.TEST_RESULT_PASSED);
                    } else {
                        showToast("Test failed. Key not accessible after auth");
                        setTestResult(mLockScreenBoundKeyTest, TestResult.TEST_RESULT_FAILED);
                    }
                } else {
                    showToast("Lockscreen challenge canceled.");
                    setTestResult(mLockScreenBoundKeyTest, TestResult.TEST_RESULT_FAILED);
                }
                break;
            default:
                super.handleActivityResult(requestCode, resultCode, data);
        }
    }

    private void showToast(String message) {
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }

    public class FingerprintAuthDialogFragment extends DialogFragment {

        private CancellationSignal mCancellationSignal;
        private FingerprintManagerCallback mFingerprintManagerCallback;
        private boolean mSelfCancelled;

        class FingerprintManagerCallback extends FingerprintManager.AuthenticationCallback {
            @Override
            public void onAuthenticationError(int errMsgId, CharSequence errString) {
                if (!mSelfCancelled) {
                    showToast(errString.toString());
                }
            }

            @Override
            public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
                showToast(helpString.toString());
            }

            @Override
            public void onAuthenticationFailed() {
                showToast(getString(R.string.sec_fp_auth_failed));
            }

            @Override
            public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
                if (tryEncryptWithFingerprintKey(mFingerprintCipher)) {
                    showToast("Test passed.");
                    setTestResult(mFingerprintBoundKeyTest, TestResult.TEST_RESULT_PASSED);
                } else {
                    showToast("Test failed. Key not accessible after auth");
                    setTestResult(mFingerprintBoundKeyTest, TestResult.TEST_RESULT_FAILED);
                }
                FingerprintAuthDialogFragment.this.dismiss();
            }
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            mCancellationSignal.cancel();
            mSelfCancelled = true;
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            mCancellationSignal = new CancellationSignal();
            mSelfCancelled = false;
            mFingerprintManagerCallback = new FingerprintManagerCallback();
            mFingerprintManager.authenticate(new FingerprintManager.CryptoObject(mFingerprintCipher),
                    mCancellationSignal, 0, mFingerprintManagerCallback, null);
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            builder.setMessage(R.string.sec_fp_dialog_message);
            return builder.create();
        }

    }

}
