2019-02-07 22:39:33 +01:00
|
|
|
package com.beemdevelopment.aegis.ui;
|
2016-09-29 12:31:55 +02:00
|
|
|
|
2017-08-06 16:03:36 +02:00
|
|
|
import android.content.Intent;
|
2016-09-29 12:31:55 +02:00
|
|
|
import android.os.Bundle;
|
2018-05-09 15:49:32 +02:00
|
|
|
import android.view.WindowManager;
|
2016-09-29 12:31:55 +02:00
|
|
|
|
2019-10-16 22:16:47 +02:00
|
|
|
import androidx.fragment.app.Fragment;
|
|
|
|
|
2019-04-04 14:07:36 +02:00
|
|
|
import com.beemdevelopment.aegis.Preferences;
|
|
|
|
import com.beemdevelopment.aegis.R;
|
2019-12-25 19:21:34 +01:00
|
|
|
import com.beemdevelopment.aegis.vault.Vault;
|
|
|
|
import com.beemdevelopment.aegis.vault.VaultFile;
|
|
|
|
import com.beemdevelopment.aegis.vault.VaultFileCredentials;
|
|
|
|
import com.beemdevelopment.aegis.vault.VaultFileException;
|
|
|
|
import com.beemdevelopment.aegis.vault.VaultManager;
|
|
|
|
import com.beemdevelopment.aegis.vault.VaultManagerException;
|
|
|
|
import com.beemdevelopment.aegis.vault.slots.BiometricSlot;
|
|
|
|
import com.beemdevelopment.aegis.vault.slots.PasswordSlot;
|
|
|
|
import com.beemdevelopment.aegis.vault.slots.Slot;
|
|
|
|
import com.beemdevelopment.aegis.vault.slots.SlotException;
|
2019-02-07 22:39:33 +01:00
|
|
|
import com.beemdevelopment.aegis.ui.slides.CustomAuthenticatedSlide;
|
|
|
|
import com.beemdevelopment.aegis.ui.slides.CustomAuthenticationSlide;
|
|
|
|
import com.beemdevelopment.aegis.ui.tasks.DerivationTask;
|
2019-04-04 14:07:36 +02:00
|
|
|
import com.github.paolorotolo.appintro.AppIntro2;
|
|
|
|
import com.github.paolorotolo.appintro.AppIntroFragment;
|
|
|
|
import com.github.paolorotolo.appintro.model.SliderPage;
|
2017-08-06 16:03:36 +02:00
|
|
|
|
2018-02-13 22:06:24 +01:00
|
|
|
import org.json.JSONObject;
|
|
|
|
|
2017-08-06 16:03:36 +02:00
|
|
|
import javax.crypto.Cipher;
|
2017-11-27 19:22:10 +01:00
|
|
|
import javax.crypto.SecretKey;
|
2017-08-06 16:03:36 +02:00
|
|
|
|
2018-09-18 23:56:25 +02:00
|
|
|
public class IntroActivity extends AppIntro2 implements DerivationTask.Callback {
|
2017-08-06 16:03:36 +02:00
|
|
|
public static final int RESULT_OK = 0;
|
|
|
|
public static final int RESULT_EXCEPTION = 1;
|
|
|
|
|
2017-08-26 21:15:53 +02:00
|
|
|
private CustomAuthenticatedSlide _authenticatedSlide;
|
|
|
|
private CustomAuthenticationSlide _authenticationSlide;
|
|
|
|
private Fragment _endSlide;
|
2016-09-29 12:31:55 +02:00
|
|
|
|
2019-12-25 19:21:34 +01:00
|
|
|
private Vault _vault;
|
|
|
|
private VaultFile _vaultFile;
|
2017-11-27 19:22:10 +01:00
|
|
|
private PasswordSlot _passwordSlot;
|
|
|
|
private Cipher _passwordCipher;
|
|
|
|
|
2018-05-11 20:08:51 +02:00
|
|
|
private Preferences _prefs;
|
2017-12-23 22:33:32 +01:00
|
|
|
|
2016-09-29 12:31:55 +02:00
|
|
|
@Override
|
2017-08-13 19:51:54 +02:00
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
2016-09-29 12:31:55 +02:00
|
|
|
super.onCreate(savedInstanceState);
|
2017-12-23 22:33:32 +01:00
|
|
|
|
2018-05-09 15:49:32 +02:00
|
|
|
// set FLAG_SECURE on the window of every IntroActivity
|
2018-05-11 20:08:51 +02:00
|
|
|
_prefs = new Preferences(this);
|
|
|
|
if (_prefs.isSecureScreenEnabled()) {
|
2018-05-11 19:33:20 +02:00
|
|
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
|
|
|
|
}
|
2018-05-09 15:49:32 +02:00
|
|
|
|
2018-06-06 18:01:35 +02:00
|
|
|
setWizardMode(true);
|
2017-08-13 19:51:54 +02:00
|
|
|
showSkipButton(false);
|
2018-06-06 18:01:35 +02:00
|
|
|
pager.setPagingEnabled(false);
|
2017-08-13 19:51:54 +02:00
|
|
|
//showPagerIndicator(false);
|
|
|
|
setGoBackLock(true);
|
2018-09-18 23:56:25 +02:00
|
|
|
setBarColor(getResources().getColor(R.color.colorPrimary));
|
2017-08-13 19:51:54 +02:00
|
|
|
|
|
|
|
SliderPage homeSliderPage = new SliderPage();
|
2018-10-09 23:13:51 +02:00
|
|
|
homeSliderPage.setTitle(getString(R.string.welcome));
|
2019-09-06 23:58:04 +02:00
|
|
|
homeSliderPage.setImageDrawable(R.drawable.app_icon);
|
2018-09-18 23:56:25 +02:00
|
|
|
homeSliderPage.setTitleColor(getResources().getColor(R.color.primary_text_dark));
|
2018-10-09 23:13:51 +02:00
|
|
|
homeSliderPage.setDescription(getString(R.string.app_description));
|
2018-09-18 23:56:25 +02:00
|
|
|
homeSliderPage.setDescColor(getResources().getColor(R.color.primary_text_dark));
|
|
|
|
homeSliderPage.setBgColor(getResources().getColor(R.color.colorSecondary));
|
2017-08-13 19:51:54 +02:00
|
|
|
addSlide(AppIntroFragment.newInstance(homeSliderPage));
|
|
|
|
|
2017-08-26 21:15:53 +02:00
|
|
|
_authenticationSlide = new CustomAuthenticationSlide();
|
2018-09-18 23:56:25 +02:00
|
|
|
_authenticationSlide.setBgColor(getResources().getColor(R.color.colorSecondary));
|
|
|
|
//_authenticationSlide.setDescColor(getResources().getColor(R.color.primary_text_dark));
|
2017-08-26 21:15:53 +02:00
|
|
|
addSlide(_authenticationSlide);
|
|
|
|
_authenticatedSlide = new CustomAuthenticatedSlide();
|
2018-09-18 23:56:25 +02:00
|
|
|
_authenticatedSlide.setBgColor(getResources().getColor(R.color.colorSecondary));
|
2017-08-26 21:15:53 +02:00
|
|
|
addSlide(_authenticatedSlide);
|
2017-08-06 16:03:36 +02:00
|
|
|
|
2017-08-13 19:51:54 +02:00
|
|
|
SliderPage endSliderPage = new SliderPage();
|
2018-10-09 23:13:51 +02:00
|
|
|
endSliderPage.setTitle(getString(R.string.setup_completed));
|
|
|
|
endSliderPage.setDescription(getString(R.string.setup_completed_description));
|
2019-09-06 23:58:04 +02:00
|
|
|
endSliderPage.setImageDrawable(R.drawable.app_icon);
|
2018-09-18 23:56:25 +02:00
|
|
|
endSliderPage.setBgColor(getResources().getColor(R.color.colorSecondary));
|
2017-08-26 21:15:53 +02:00
|
|
|
_endSlide = AppIntroFragment.newInstance(endSliderPage);
|
|
|
|
addSlide(_endSlide);
|
2017-11-27 19:22:10 +01:00
|
|
|
|
2019-12-25 19:21:34 +01:00
|
|
|
_vault = new Vault();
|
|
|
|
_vaultFile = new VaultFile();
|
2017-08-06 16:03:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private void setException(Exception e) {
|
|
|
|
Intent result = new Intent();
|
|
|
|
result.putExtra("exception", e);
|
2017-08-07 22:38:36 +02:00
|
|
|
setResult(RESULT_EXCEPTION, result);
|
2017-08-13 19:51:54 +02:00
|
|
|
finish();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSlideChanged(Fragment oldFragment, Fragment newFragment) {
|
2017-11-27 19:22:10 +01:00
|
|
|
Intent intent = getIntent();
|
|
|
|
int cryptType = intent.getIntExtra("cryptType", CustomAuthenticationSlide.CRYPT_TYPE_INVALID);
|
|
|
|
|
|
|
|
if (newFragment == _endSlide && cryptType != CustomAuthenticationSlide.CRYPT_TYPE_NONE) {
|
|
|
|
_passwordSlot = new PasswordSlot();
|
2018-06-06 21:30:24 +02:00
|
|
|
DerivationTask.Params params = new DerivationTask.Params(_passwordSlot, _authenticatedSlide.getPassword());
|
|
|
|
new DerivationTask(this, this).execute(params);
|
2017-11-27 19:22:10 +01:00
|
|
|
} else if (oldFragment == _authenticationSlide && newFragment != _endSlide) {
|
|
|
|
// skip to the last slide if no encryption will be used
|
2017-08-13 19:51:54 +02:00
|
|
|
if (cryptType == CustomAuthenticationSlide.CRYPT_TYPE_NONE) {
|
|
|
|
// TODO: no magic indices
|
2018-06-06 18:01:35 +02:00
|
|
|
getPager().setCurrentItem(4);
|
2017-08-13 19:51:54 +02:00
|
|
|
}
|
|
|
|
}
|
2016-09-29 12:31:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-08-13 19:51:54 +02:00
|
|
|
public void onDonePressed(Fragment currentFragment) {
|
|
|
|
super.onDonePressed(currentFragment);
|
2017-12-10 19:22:00 +01:00
|
|
|
|
|
|
|
int cryptType = _authenticatedSlide.getCryptType();
|
2017-11-27 19:23:21 +01:00
|
|
|
// wait for the key derivation background task
|
2017-12-11 14:01:43 +01:00
|
|
|
if (cryptType != CustomAuthenticationSlide.CRYPT_TYPE_NONE &&
|
|
|
|
(_passwordSlot == null || _passwordCipher == null)) {
|
2017-11-27 19:23:21 +01:00
|
|
|
return;
|
|
|
|
}
|
2017-08-06 16:03:36 +02:00
|
|
|
|
2017-08-06 21:45:27 +02:00
|
|
|
// generate the master key
|
2019-12-25 19:21:34 +01:00
|
|
|
VaultFileCredentials creds = null;
|
2017-08-06 21:45:27 +02:00
|
|
|
if (cryptType != CustomAuthenticationSlide.CRYPT_TYPE_NONE) {
|
2019-12-25 19:21:34 +01:00
|
|
|
creds = new VaultFileCredentials();
|
2017-08-06 21:45:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cryptType != CustomAuthenticationSlide.CRYPT_TYPE_NONE) {
|
2018-03-19 18:00:53 +01:00
|
|
|
// encrypt the master key with a key derived from the user's password
|
|
|
|
// and add it to the list of slots
|
|
|
|
if (_passwordSlot == null || _passwordCipher == null) {
|
|
|
|
throw new RuntimeException();
|
|
|
|
}
|
2017-08-06 21:45:27 +02:00
|
|
|
try {
|
2018-10-06 22:23:38 +02:00
|
|
|
_passwordSlot.setKey(creds.getKey(), _passwordCipher);
|
|
|
|
creds.getSlots().add(_passwordSlot);
|
2018-03-19 18:00:53 +01:00
|
|
|
} catch (SlotException e) {
|
2017-08-06 21:45:27 +02:00
|
|
|
setException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-16 22:16:47 +02:00
|
|
|
if (cryptType == CustomAuthenticationSlide.CRYPT_TYPE_BIOMETRIC) {
|
|
|
|
BiometricSlot slot = _authenticatedSlide.getBiometricSlot();
|
2017-08-13 23:38:38 +02:00
|
|
|
try {
|
2019-10-16 22:16:47 +02:00
|
|
|
slot.setKey(creds.getKey(), _authenticatedSlide.getBiometriCipher());
|
2018-03-19 18:00:53 +01:00
|
|
|
} catch (SlotException e) {
|
2017-08-13 23:38:38 +02:00
|
|
|
setException(e);
|
|
|
|
}
|
2019-10-16 22:16:47 +02:00
|
|
|
creds.getSlots().add(slot);
|
2017-08-06 21:45:27 +02:00
|
|
|
}
|
|
|
|
|
2019-12-25 19:21:34 +01:00
|
|
|
// finally, save the vault
|
2017-08-06 16:03:36 +02:00
|
|
|
try {
|
2019-12-25 19:21:34 +01:00
|
|
|
JSONObject obj = _vault.toJson();
|
2017-08-06 21:45:27 +02:00
|
|
|
if (cryptType == CustomAuthenticationSlide.CRYPT_TYPE_NONE) {
|
2019-12-25 19:21:34 +01:00
|
|
|
_vaultFile.setContent(obj);
|
2017-08-06 21:45:27 +02:00
|
|
|
} else {
|
2019-12-25 19:21:34 +01:00
|
|
|
_vaultFile.setContent(obj, creds);
|
2017-08-06 21:45:27 +02:00
|
|
|
}
|
2019-12-25 19:21:34 +01:00
|
|
|
VaultManager.save(getApplicationContext(), _vaultFile);
|
|
|
|
} catch (VaultManagerException | VaultFileException e) {
|
2017-08-06 16:03:36 +02:00
|
|
|
setException(e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// send the master key back to the main activity
|
|
|
|
Intent result = new Intent();
|
2018-10-06 22:23:38 +02:00
|
|
|
result.putExtra("creds", creds);
|
2017-08-06 16:03:36 +02:00
|
|
|
setResult(RESULT_OK, result);
|
|
|
|
|
|
|
|
// skip the intro from now on
|
2018-05-11 20:08:51 +02:00
|
|
|
_prefs.setIntroDone(true);
|
2017-08-13 19:51:54 +02:00
|
|
|
finish();
|
2016-09-29 12:31:55 +02:00
|
|
|
}
|
2017-11-27 19:22:10 +01:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onTaskFinished(SecretKey key) {
|
|
|
|
if (key != null) {
|
|
|
|
try {
|
2018-06-06 19:38:13 +02:00
|
|
|
_passwordCipher = Slot.createEncryptCipher(key);
|
2018-03-19 18:00:53 +01:00
|
|
|
} catch (SlotException e) {
|
2017-11-27 19:22:10 +01:00
|
|
|
setException(e);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
setException(new NullPointerException());
|
|
|
|
}
|
|
|
|
}
|
2016-09-29 12:31:55 +02:00
|
|
|
}
|