Aegis/app/src/main/java/com/beemdevelopment/aegis/ui/AuthActivity.java

196 lines
7.3 KiB
Java
Raw Normal View History

package com.beemdevelopment.aegis.ui;
import android.content.Context;
import android.content.Intent;
2017-08-13 23:38:38 +02:00
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
2019-04-14 00:38:19 +02:00
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
2017-08-13 23:38:38 +02:00
import android.widget.LinearLayout;
import android.widget.TextView;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.crypto.KeyStoreHandle;
import com.beemdevelopment.aegis.crypto.KeyStoreHandleException;
import com.beemdevelopment.aegis.crypto.MasterKey;
import com.beemdevelopment.aegis.db.DatabaseFileCredentials;
import com.beemdevelopment.aegis.db.slots.FingerprintSlot;
import com.beemdevelopment.aegis.db.slots.PasswordSlot;
import com.beemdevelopment.aegis.db.slots.Slot;
import com.beemdevelopment.aegis.db.slots.SlotException;
import com.beemdevelopment.aegis.db.slots.SlotList;
import com.beemdevelopment.aegis.helpers.EditTextHelper;
import com.beemdevelopment.aegis.helpers.FingerprintHelper;
import com.beemdevelopment.aegis.helpers.FingerprintUiHelper;
import com.beemdevelopment.aegis.ui.tasks.SlotListTask;
import com.mattprecious.swirl.SwirlView;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import androidx.appcompat.app.AlertDialog;
public class AuthActivity extends AegisActivity implements FingerprintUiHelper.Callback, SlotListTask.Callback {
2017-08-26 21:15:53 +02:00
private EditText _textPassword;
private SlotList _slots;
2017-08-26 21:15:53 +02:00
private FingerprintUiHelper _fingerHelper;
private FingerprintManager.CryptoObject _fingerCryptoObj;
2017-08-13 23:38:38 +02:00
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_auth);
_textPassword = findViewById(R.id.text_password);
LinearLayout boxFingerprint = findViewById(R.id.box_fingerprint);
LinearLayout boxFingerprintInfo = findViewById(R.id.box_fingerprint_info);
TextView textFingerprint = findViewById(R.id.text_fingerprint);
Button decryptButton = findViewById(R.id.button_decrypt);
_textPassword.setOnEditorActionListener((v, actionId, event) -> {
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
decryptButton.performClick();
}
return false;
});
SwirlView imgFingerprint = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ViewGroup insertPoint = findViewById(R.id.img_fingerprint_insert);
imgFingerprint = new SwirlView(this);
insertPoint.addView(imgFingerprint, 0, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
Intent intent = getIntent();
_slots = (SlotList) intent.getSerializableExtra("slots");
2017-08-13 23:38:38 +02:00
// only show the fingerprint controls if the api version is new enough, permission is granted, a scanner is found and a fingerprint slot is found
FingerprintManager manager = FingerprintHelper.getManager(this);
if (manager != null && _slots.has(FingerprintSlot.class)) {
boolean invalidated = false;
try {
2018-02-10 17:20:41 +01:00
// find a fingerprint slot with an id that matches an alias in the keystore
for (FingerprintSlot slot : _slots.findAll(FingerprintSlot.class)) {
String id = slot.getUUID().toString();
2018-02-10 17:20:41 +01:00
KeyStoreHandle handle = new KeyStoreHandle();
if (handle.containsKey(id)) {
SecretKey key = handle.getKey(id);
// if 'key' is null, it was permanently invalidated
if (key == null) {
invalidated = true;
continue;
}
Cipher cipher = slot.createDecryptCipher(key);
_fingerCryptoObj = new FingerprintManager.CryptoObject(cipher);
2018-02-10 17:20:41 +01:00
_fingerHelper = new FingerprintUiHelper(manager, imgFingerprint, textFingerprint, this);
boxFingerprint.setVisibility(View.VISIBLE);
invalidated = false;
2018-02-10 17:20:41 +01:00
break;
}
2017-08-13 23:38:38 +02:00
}
} catch (KeyStoreHandleException | SlotException e) {
throw new RuntimeException(e);
2017-08-13 23:38:38 +02:00
}
// display a help message if a matching invalidated keystore entry was found
if (invalidated) {
boxFingerprintInfo.setVisibility(View.VISIBLE);
}
2017-08-13 23:38:38 +02:00
}
decryptButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
char[] password = EditTextHelper.getEditTextChars(_textPassword);
trySlots(PasswordSlot.class, password);
}
});
2019-04-14 00:38:19 +02:00
if (_fingerHelper == null) {
_textPassword.requestFocus();
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
}
}
private void showError() {
Dialogs.showSecureDialog(new AlertDialog.Builder(this)
.setTitle(getString(R.string.unlock_vault_error))
.setMessage(getString(R.string.unlock_vault_error_description))
.setCancelable(false)
.setPositiveButton(android.R.string.ok, (dialog, which) -> selectPassword())
.create());
}
private <T extends Slot> void trySlots(Class<T> type, Object obj) {
SlotListTask.Params params = new SlotListTask.Params(_slots, obj);
new SlotListTask<>(type, this, this).execute(params);
}
private void setKey(MasterKey key) {
2017-08-13 23:38:38 +02:00
// send the master key back to the main activity
Intent result = new Intent();
result.putExtra("creds", new DatabaseFileCredentials(key, _slots));
2017-08-13 23:38:38 +02:00
setResult(RESULT_OK, result);
finish();
}
private void selectPassword() {
_textPassword.selectAll();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
@Override
public void onBackPressed() {
// ignore back button presses
}
2017-08-13 23:38:38 +02:00
@Override
public void onResume() {
super.onResume();
2017-08-26 21:15:53 +02:00
if (_fingerHelper != null) {
_fingerHelper.startListening(_fingerCryptoObj);
2017-08-13 23:38:38 +02:00
}
}
@Override
public void onPause() {
super.onPause();
2017-08-26 21:15:53 +02:00
if (_fingerHelper != null) {
_fingerHelper.stopListening();
}
}
2017-08-13 23:38:38 +02:00
@Override
public void onAuthenticated() {
trySlots(FingerprintSlot.class, _fingerCryptoObj.getCipher());
2017-08-13 23:38:38 +02:00
}
@Override
public void onError() {
}
@Override
public void onTaskFinished(MasterKey key) {
if (key != null) {
setKey(key);
} else {
showError();
}
}
}