2017-08-06 18:15:47 +02:00
|
|
|
package me.impy.aegis;
|
|
|
|
|
2017-08-13 23:38:38 +02:00
|
|
|
import android.Manifest;
|
|
|
|
import android.content.Context;
|
2017-08-18 22:12:45 +02:00
|
|
|
import android.content.DialogInterface;
|
2017-08-06 18:15:47 +02:00
|
|
|
import android.content.Intent;
|
2017-08-13 23:38:38 +02:00
|
|
|
import android.content.pm.PackageManager;
|
|
|
|
import android.hardware.fingerprint.FingerprintManager;
|
|
|
|
import android.os.Build;
|
|
|
|
import android.support.v4.app.ActivityCompat;
|
2017-08-18 22:12:45 +02:00
|
|
|
import android.support.v7.app.AlertDialog;
|
2017-08-06 18:15:47 +02:00
|
|
|
import android.support.v7.app.AppCompatActivity;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.view.View;
|
|
|
|
import android.widget.Button;
|
|
|
|
import android.widget.EditText;
|
2017-08-13 23:38:38 +02:00
|
|
|
import android.widget.LinearLayout;
|
|
|
|
import android.widget.TextView;
|
2017-08-06 18:15:47 +02:00
|
|
|
|
2017-08-19 16:48:57 +02:00
|
|
|
import com.mattprecious.swirl.SwirlView;
|
|
|
|
|
2017-08-06 18:15:47 +02:00
|
|
|
import java.lang.reflect.UndeclaredThrowableException;
|
|
|
|
|
|
|
|
import javax.crypto.Cipher;
|
|
|
|
import javax.crypto.SecretKey;
|
|
|
|
|
|
|
|
import me.impy.aegis.crypto.CryptoUtils;
|
2017-08-13 23:38:38 +02:00
|
|
|
import me.impy.aegis.crypto.KeyStoreHandle;
|
2017-08-06 18:15:47 +02:00
|
|
|
import me.impy.aegis.crypto.MasterKey;
|
2017-08-13 23:38:38 +02:00
|
|
|
import me.impy.aegis.crypto.slots.FingerprintSlot;
|
2017-08-06 18:15:47 +02:00
|
|
|
import me.impy.aegis.crypto.slots.PasswordSlot;
|
|
|
|
import me.impy.aegis.crypto.slots.Slot;
|
|
|
|
import me.impy.aegis.crypto.slots.SlotCollection;
|
2017-08-19 13:50:33 +02:00
|
|
|
import me.impy.aegis.crypto.slots.SlotIntegrityException;
|
2017-08-13 23:38:38 +02:00
|
|
|
import me.impy.aegis.finger.FingerprintUiHelper;
|
|
|
|
import me.impy.aegis.helpers.AuthHelper;
|
2017-08-06 18:15:47 +02:00
|
|
|
|
2017-08-13 23:38:38 +02:00
|
|
|
public class AuthActivity extends AppCompatActivity implements FingerprintUiHelper.Callback {
|
2017-08-06 18:15:47 +02:00
|
|
|
public static final int RESULT_OK = 0;
|
|
|
|
public static final int RESULT_EXCEPTION = 1;
|
|
|
|
|
|
|
|
private EditText textPassword;
|
|
|
|
|
2017-08-13 23:38:38 +02:00
|
|
|
private SlotCollection slots;
|
|
|
|
private LinearLayout boxFingerprint;
|
2017-08-19 16:48:57 +02:00
|
|
|
private SwirlView imgFingerprint;
|
2017-08-13 23:38:38 +02:00
|
|
|
private TextView textFingerprint;
|
|
|
|
private FingerprintUiHelper fingerHelper;
|
|
|
|
private Cipher fingerCipher;
|
|
|
|
|
2017-08-06 18:15:47 +02:00
|
|
|
@Override
|
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
setContentView(R.layout.activity_auth);
|
|
|
|
textPassword = (EditText) findViewById(R.id.text_password);
|
2017-08-13 23:38:38 +02:00
|
|
|
boxFingerprint = (LinearLayout) findViewById(R.id.box_fingerprint);
|
2017-08-19 16:48:57 +02:00
|
|
|
imgFingerprint = (SwirlView) findViewById(R.id.img_fingerprint);
|
2017-08-13 23:38:38 +02:00
|
|
|
textFingerprint = (TextView) findViewById(R.id.text_fingerprint);
|
2017-08-06 18:15:47 +02:00
|
|
|
|
|
|
|
Intent intent = getIntent();
|
2017-08-13 23:38:38 +02:00
|
|
|
slots = (SlotCollection) intent.getSerializableExtra("slots");
|
|
|
|
|
|
|
|
// 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
|
|
|
|
Context context = getApplicationContext();
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
|
|
FingerprintManager manager = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
|
|
|
|
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.USE_FINGERPRINT) == PackageManager.PERMISSION_GRANTED && manager.isHardwareDetected()) {
|
|
|
|
if (slots.has(FingerprintSlot.class)) {
|
|
|
|
try {
|
|
|
|
KeyStoreHandle handle = new KeyStoreHandle();
|
|
|
|
if (handle.keyExists()) {
|
|
|
|
SecretKey key = handle.getKey();
|
|
|
|
fingerCipher = Slot.createCipher(key, Cipher.DECRYPT_MODE);
|
|
|
|
fingerHelper = new FingerprintUiHelper(manager, imgFingerprint, textFingerprint, this);
|
|
|
|
boxFingerprint.setVisibility(View.VISIBLE);
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
throw new UndeclaredThrowableException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-08-06 18:15:47 +02:00
|
|
|
|
|
|
|
Button button = (Button) findViewById(R.id.button_decrypt);
|
|
|
|
button.setOnClickListener(new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(View v) {
|
2017-08-19 13:50:33 +02:00
|
|
|
trySlots(PasswordSlot.class);
|
2017-08-06 18:15:47 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-08-19 13:50:33 +02:00
|
|
|
private void showError() {
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
|
|
builder.setMessage("Master key integrity check failed for every slot. Make sure you didn't mistype your password.");
|
|
|
|
builder.setCancelable(false);
|
|
|
|
builder.setPositiveButton("OK",
|
2017-08-18 22:12:45 +02:00
|
|
|
new DialogInterface.OnClickListener() {
|
|
|
|
public void onClick(DialogInterface dialog, int id) {
|
|
|
|
dialog.cancel();
|
|
|
|
}
|
|
|
|
});
|
2017-08-19 13:50:33 +02:00
|
|
|
builder.create().show();
|
|
|
|
}
|
|
|
|
|
|
|
|
private MasterKey decryptPasswordSlot(PasswordSlot slot) throws Exception {
|
|
|
|
char[] password = AuthHelper.getPassword(textPassword, true);
|
|
|
|
SecretKey key = slot.deriveKey(password);
|
|
|
|
CryptoUtils.zero(password);
|
|
|
|
Cipher cipher = Slot.createCipher(key, Cipher.DECRYPT_MODE);
|
|
|
|
return slots.decrypt(slot, cipher);
|
|
|
|
}
|
|
|
|
|
|
|
|
private MasterKey decryptFingerSlot(FingerprintSlot slot) throws Exception {
|
|
|
|
return slots.decrypt(slot, fingerCipher);
|
|
|
|
}
|
|
|
|
|
|
|
|
private <T extends Slot> void trySlots(Class<T> type) {
|
|
|
|
try {
|
|
|
|
if (!slots.has(type)) {
|
|
|
|
throw new RuntimeException();
|
|
|
|
}
|
|
|
|
|
|
|
|
MasterKey masterKey = null;
|
|
|
|
for (Slot slot : slots.findAll(type)) {
|
|
|
|
try {
|
|
|
|
if (slot instanceof PasswordSlot) {
|
|
|
|
masterKey = decryptPasswordSlot((PasswordSlot) slot);
|
|
|
|
} else if (slot instanceof FingerprintSlot) {
|
|
|
|
masterKey = decryptFingerSlot((FingerprintSlot) slot);
|
|
|
|
} else {
|
|
|
|
throw new RuntimeException();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
} catch (SlotIntegrityException e) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (masterKey == null) {
|
|
|
|
throw new SlotIntegrityException();
|
|
|
|
}
|
|
|
|
|
|
|
|
setKey(masterKey);
|
|
|
|
} catch (SlotIntegrityException e) {
|
|
|
|
showError();
|
|
|
|
} catch (Exception e) {
|
|
|
|
throw new UndeclaredThrowableException(e);
|
2017-08-18 22:12:45 +02:00
|
|
|
}
|
2017-08-19 13:50:33 +02:00
|
|
|
}
|
2017-08-18 22:12:45 +02:00
|
|
|
|
2017-08-19 13:50:33 +02:00
|
|
|
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("key", key);
|
|
|
|
setResult(RESULT_OK, result);
|
|
|
|
finish();
|
|
|
|
}
|
|
|
|
|
2017-08-13 19:55:53 +02:00
|
|
|
@Override
|
|
|
|
public void onBackPressed() {
|
|
|
|
// ignore back button presses
|
|
|
|
}
|
|
|
|
|
2017-08-13 23:38:38 +02:00
|
|
|
@Override
|
|
|
|
public void onResume() {
|
|
|
|
super.onResume();
|
|
|
|
|
|
|
|
if (fingerHelper != null) {
|
|
|
|
fingerHelper.startListening(new FingerprintManager.CryptoObject(fingerCipher));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPause() {
|
|
|
|
super.onPause();
|
|
|
|
|
|
|
|
if (fingerHelper != null) {
|
|
|
|
fingerHelper.stopListening();
|
2017-08-06 18:15:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-13 23:38:38 +02:00
|
|
|
@Override
|
|
|
|
public void onAuthenticated() {
|
2017-08-19 13:50:33 +02:00
|
|
|
trySlots(FingerprintSlot.class);
|
2017-08-13 23:38:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onError() {
|
|
|
|
|
2017-08-06 18:15:47 +02:00
|
|
|
}
|
|
|
|
}
|