Aegis/app/src/main/java/me/impy/aegis/ui/IntroActivity.java

204 lines
7.7 KiB
Java
Raw Normal View History

package me.impy.aegis.ui;
import android.content.Intent;
import android.os.Bundle;
2018-09-25 16:26:57 +02:00
import androidx.fragment.app.Fragment;
2018-05-09 15:49:32 +02:00
import android.view.WindowManager;
2018-09-18 23:56:25 +02:00
import com.github.paolorotolo.appintro.AppIntro2;
import com.github.paolorotolo.appintro.AppIntroFragment;
import com.github.paolorotolo.appintro.model.SliderPage;
import org.json.JSONObject;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import me.impy.aegis.Preferences;
import me.impy.aegis.R;
import me.impy.aegis.db.DatabaseFileCredentials;
import me.impy.aegis.db.DatabaseFileException;
import me.impy.aegis.db.DatabaseManagerException;
import me.impy.aegis.db.slots.FingerprintSlot;
import me.impy.aegis.db.slots.PasswordSlot;
import me.impy.aegis.db.slots.Slot;
import me.impy.aegis.db.slots.SlotList;
import me.impy.aegis.db.Database;
import me.impy.aegis.db.DatabaseFile;
2017-12-04 22:08:50 +01:00
import me.impy.aegis.db.DatabaseManager;
import me.impy.aegis.db.slots.SlotException;
import me.impy.aegis.ui.slides.CustomAuthenticatedSlide;
import me.impy.aegis.ui.slides.CustomAuthenticationSlide;
import me.impy.aegis.ui.tasks.DerivationTask;
2018-09-18 23:56:25 +02:00
public class IntroActivity extends AppIntro2 implements DerivationTask.Callback {
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;
private Database _database;
private DatabaseFile _databaseFile;
private PasswordSlot _passwordSlot;
private Cipher _passwordCipher;
private Preferences _prefs;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
2018-05-09 15:49:32 +02:00
// set FLAG_SECURE on the window of every IntroActivity
_prefs = new Preferences(this);
if (_prefs.isSecureScreenEnabled()) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
2018-05-09 15:49:32 +02:00
2018-06-06 18:01:35 +02:00
setWizardMode(true);
showSkipButton(false);
2018-06-06 18:01:35 +02:00
pager.setPagingEnabled(false);
//showPagerIndicator(false);
setGoBackLock(true);
2018-09-18 23:56:25 +02:00
setBarColor(getResources().getColor(R.color.colorPrimary));
SliderPage homeSliderPage = new SliderPage();
2018-10-09 23:13:51 +02:00
homeSliderPage.setTitle(getString(R.string.welcome));
2018-10-10 21:41:30 +02:00
homeSliderPage.setImageDrawable(R.drawable.icon_foreground_white);
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));
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);
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));
endSliderPage.setImageDrawable(R.drawable.icon_foreground_white);
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);
// create the database and database file
_database = new Database();
_databaseFile = new DatabaseFile();
}
private void setException(Exception e) {
Intent result = new Intent();
result.putExtra("exception", e);
setResult(RESULT_EXCEPTION, result);
finish();
}
@Override
public void onSlideChanged(Fragment oldFragment, Fragment newFragment) {
Intent intent = getIntent();
int cryptType = intent.getIntExtra("cryptType", CustomAuthenticationSlide.CRYPT_TYPE_INVALID);
if (newFragment == _endSlide && cryptType != CustomAuthenticationSlide.CRYPT_TYPE_NONE) {
_passwordSlot = new PasswordSlot();
DerivationTask.Params params = new DerivationTask.Params(_passwordSlot, _authenticatedSlide.getPassword());
new DerivationTask(this, this).execute(params);
} else if (oldFragment == _authenticationSlide && newFragment != _endSlide) {
// skip to the last slide if no encryption will be used
if (cryptType == CustomAuthenticationSlide.CRYPT_TYPE_NONE) {
// TODO: no magic indices
2018-06-06 18:01:35 +02:00
getPager().setCurrentItem(4);
}
}
}
@Override
public void onDonePressed(Fragment currentFragment) {
super.onDonePressed(currentFragment);
int cryptType = _authenticatedSlide.getCryptType();
// 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)) {
return;
}
2017-08-06 21:45:27 +02:00
// generate the master key
DatabaseFileCredentials creds = null;
2017-08-06 21:45:27 +02:00
if (cryptType != CustomAuthenticationSlide.CRYPT_TYPE_NONE) {
creds = new DatabaseFileCredentials();
2017-08-06 21:45:27 +02:00
}
SlotList slots = null;
2017-08-06 21:45:27 +02:00
if (cryptType != CustomAuthenticationSlide.CRYPT_TYPE_NONE) {
// 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 {
_passwordSlot.setKey(creds.getKey(), _passwordCipher);
creds.getSlots().add(_passwordSlot);
} catch (SlotException e) {
2017-08-06 21:45:27 +02:00
setException(e);
}
}
2017-08-13 23:38:38 +02:00
if (cryptType == CustomAuthenticationSlide.CRYPT_TYPE_FINGER) {
try {
// encrypt the master key with the fingerprint key
// and add it to the list of slots
FingerprintSlot slot = _authenticatedSlide.getFingerSlot();
Cipher cipher = _authenticatedSlide.getFingerCipher();
slot.setKey(creds.getKey(), cipher);
creds.getSlots().add(slot);
} catch (SlotException e) {
2017-08-13 23:38:38 +02:00
setException(e);
return;
}
2017-08-06 21:45:27 +02:00
}
// finally, save the database
try {
JSONObject obj = _database.toJson();
2017-08-06 21:45:27 +02:00
if (cryptType == CustomAuthenticationSlide.CRYPT_TYPE_NONE) {
_databaseFile.setContent(obj);
2017-08-06 21:45:27 +02:00
} else {
_databaseFile.setContent(obj, creds);
2017-08-06 21:45:27 +02:00
}
DatabaseManager.save(getApplicationContext(), _databaseFile);
} catch (DatabaseManagerException | DatabaseFileException e) {
setException(e);
return;
}
// send the master key back to the main activity
Intent result = new Intent();
result.putExtra("creds", creds);
setResult(RESULT_OK, result);
// skip the intro from now on
_prefs.setIntroDone(true);
finish();
}
@Override
public void onTaskFinished(SecretKey key) {
if (key != null) {
try {
_passwordCipher = Slot.createEncryptCipher(key);
} catch (SlotException e) {
setException(e);
}
} else {
setException(new NullPointerException());
}
}
}