mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-04-24 07:46:07 +00:00
Display a message if all fingerprint slots have been invalidated
This commit is contained in:
parent
576f908e01
commit
a52c5b61c0
4 changed files with 72 additions and 9 deletions
|
@ -15,6 +15,7 @@ import android.widget.TextView;
|
||||||
import com.mattprecious.swirl.SwirlView;
|
import com.mattprecious.swirl.SwirlView;
|
||||||
|
|
||||||
import java.lang.reflect.UndeclaredThrowableException;
|
import java.lang.reflect.UndeclaredThrowableException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
|
@ -30,9 +31,6 @@ import me.impy.aegis.helpers.FingerprintUiHelper;
|
||||||
import me.impy.aegis.helpers.AuthHelper;
|
import me.impy.aegis.helpers.AuthHelper;
|
||||||
|
|
||||||
public class AuthActivity extends AegisActivity implements FingerprintUiHelper.Callback, SlotCollectionTask.Callback {
|
public class AuthActivity extends AegisActivity implements FingerprintUiHelper.Callback, SlotCollectionTask.Callback {
|
||||||
public static final int RESULT_OK = 0;
|
|
||||||
public static final int RESULT_EXCEPTION = 1;
|
|
||||||
|
|
||||||
private EditText _textPassword;
|
private EditText _textPassword;
|
||||||
|
|
||||||
private SlotCollection _slots;
|
private SlotCollection _slots;
|
||||||
|
@ -45,6 +43,7 @@ public class AuthActivity extends AegisActivity implements FingerprintUiHelper.C
|
||||||
setContentView(R.layout.activity_auth);
|
setContentView(R.layout.activity_auth);
|
||||||
_textPassword = findViewById(R.id.text_password);
|
_textPassword = findViewById(R.id.text_password);
|
||||||
LinearLayout boxFingerprint = findViewById(R.id.box_fingerprint);
|
LinearLayout boxFingerprint = findViewById(R.id.box_fingerprint);
|
||||||
|
LinearLayout boxFingerprintInfo = findViewById(R.id.box_fingerprint_info);
|
||||||
TextView textFingerprint = findViewById(R.id.text_fingerprint);
|
TextView textFingerprint = findViewById(R.id.text_fingerprint);
|
||||||
|
|
||||||
SwirlView imgFingerprint = null;
|
SwirlView imgFingerprint = null;
|
||||||
|
@ -60,6 +59,7 @@ public class AuthActivity extends AegisActivity implements FingerprintUiHelper.C
|
||||||
// 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
|
// 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);
|
FingerprintManager manager = FingerprintHelper.getManager(this);
|
||||||
if (manager != null && _slots.has(FingerprintSlot.class)) {
|
if (manager != null && _slots.has(FingerprintSlot.class)) {
|
||||||
|
boolean invalidated = false;
|
||||||
try {
|
try {
|
||||||
// find a fingerprint slot with an id that matches an alias in the keystore
|
// find a fingerprint slot with an id that matches an alias in the keystore
|
||||||
for (FingerprintSlot slot : _slots.findAll(FingerprintSlot.class)) {
|
for (FingerprintSlot slot : _slots.findAll(FingerprintSlot.class)) {
|
||||||
|
@ -67,15 +67,26 @@ public class AuthActivity extends AegisActivity implements FingerprintUiHelper.C
|
||||||
KeyStoreHandle handle = new KeyStoreHandle();
|
KeyStoreHandle handle = new KeyStoreHandle();
|
||||||
if (handle.containsKey(id)) {
|
if (handle.containsKey(id)) {
|
||||||
SecretKey key = handle.getKey(id);
|
SecretKey key = handle.getKey(id);
|
||||||
|
// if 'key' is null, it was permanently invalidated
|
||||||
|
if (key == null) {
|
||||||
|
invalidated = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
_fingerCipher = Slot.createCipher(key, Cipher.DECRYPT_MODE);
|
_fingerCipher = Slot.createCipher(key, Cipher.DECRYPT_MODE);
|
||||||
_fingerHelper = new FingerprintUiHelper(manager, imgFingerprint, textFingerprint, this);
|
_fingerHelper = new FingerprintUiHelper(manager, imgFingerprint, textFingerprint, this);
|
||||||
boxFingerprint.setVisibility(View.VISIBLE);
|
boxFingerprint.setVisibility(View.VISIBLE);
|
||||||
|
invalidated = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new UndeclaredThrowableException(e);
|
throw new UndeclaredThrowableException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// display a help message if a matching invalidated keystore entry was found
|
||||||
|
if (invalidated) {
|
||||||
|
boxFingerprintInfo.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Button button = findViewById(R.id.button_decrypt);
|
Button button = findViewById(R.id.button_decrypt);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import me.impy.aegis.crypto.KeyStoreHandle;
|
||||||
import me.impy.aegis.crypto.slots.FingerprintSlot;
|
import me.impy.aegis.crypto.slots.FingerprintSlot;
|
||||||
import me.impy.aegis.crypto.slots.PasswordSlot;
|
import me.impy.aegis.crypto.slots.PasswordSlot;
|
||||||
import me.impy.aegis.crypto.slots.RawSlot;
|
import me.impy.aegis.crypto.slots.RawSlot;
|
||||||
|
@ -29,13 +30,19 @@ public class SlotHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
public void setData(Slot slot) {
|
public void setData(Slot slot) {
|
||||||
if (slot instanceof PasswordSlot) {
|
if (slot instanceof PasswordSlot) {
|
||||||
_slotName.setText("Password 1");
|
_slotName.setText("Password");
|
||||||
_slotImg.setImageResource(R.drawable.ic_create_black_24dp);
|
_slotImg.setImageResource(R.drawable.ic_create_black_24dp);
|
||||||
} else if (slot instanceof FingerprintSlot) {
|
} else if (slot instanceof FingerprintSlot) {
|
||||||
_slotName.setText("Finger 1");
|
_slotName.setText("Finger");
|
||||||
_slotImg.setImageResource(R.drawable.ic_fingerprint_black_24dp);
|
_slotImg.setImageResource(R.drawable.ic_fingerprint_black_24dp);
|
||||||
|
try {
|
||||||
|
KeyStoreHandle keyStore = new KeyStoreHandle();
|
||||||
|
if (keyStore.containsKey(slot.getID())) {
|
||||||
|
_slotUsed.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
} catch (Exception e) { }
|
||||||
} else if (slot instanceof RawSlot) {
|
} else if (slot instanceof RawSlot) {
|
||||||
_slotName.setText("Raw 1");
|
_slotName.setText("Raw");
|
||||||
_slotImg.setImageResource(R.drawable.ic_vpn_key_black_24dp);
|
_slotImg.setImageResource(R.drawable.ic_vpn_key_black_24dp);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
package me.impy.aegis.crypto;
|
package me.impy.aegis.crypto;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.security.keystore.KeyGenParameterSpec;
|
import android.security.keystore.KeyGenParameterSpec;
|
||||||
|
import android.security.keystore.KeyPermanentlyInvalidatedException;
|
||||||
import android.security.keystore.KeyProperties;
|
import android.security.keystore.KeyProperties;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.UnrecoverableKeyException;
|
import java.security.UnrecoverableKeyException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.KeyGenerator;
|
import javax.crypto.KeyGenerator;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
|
|
||||||
import me.impy.aegis.crypto.slots.FingerprintSlot;
|
import me.impy.aegis.crypto.slots.FingerprintSlot;
|
||||||
|
@ -47,7 +52,28 @@ public class KeyStoreHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecretKey getKey(String id) throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException {
|
public SecretKey getKey(String id)
|
||||||
return (SecretKey) _keyStore.getKey(id, null);
|
throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException {
|
||||||
|
SecretKey key = (SecretKey) _keyStore.getKey(id, null);
|
||||||
|
|
||||||
|
// try to initialize a dummy cipher
|
||||||
|
// and see if KeyPermanentlyInvalidatedException is thrown
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
try {
|
||||||
|
@SuppressLint("GetInstance")
|
||||||
|
Cipher cipher = Cipher.getInstance(CryptoUtils.CRYPTO_CIPHER_RAW);
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, key);
|
||||||
|
} catch (KeyPermanentlyInvalidatedException e) {
|
||||||
|
return null;
|
||||||
|
} catch (NoSuchPaddingException | InvalidKeyException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteKey(String id) throws KeyStoreException {
|
||||||
|
_keyStore.deleteEntry(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="12dp"
|
||||||
android:visibility="invisible">
|
android:visibility="gone">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/img_fingerprint_insert"
|
android:id="@+id/img_fingerprint_insert"
|
||||||
|
@ -65,5 +65,24 @@
|
||||||
android:text="@string/fingerprint_hint"
|
android:text="@string/fingerprint_hint"
|
||||||
android:textColor="?attr/secondaryText"/>
|
android:textColor="?attr/secondaryText"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/box_fingerprint_info"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingTop="12dp"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_info_outline_black_24dp"
|
||||||
|
android:layout_marginEnd="15dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="A fingerprint slot was found, but it appears to have been invalidated by the Android keystore. Go to "Settings -> Key slots" to readd your fingerprint."/>
|
||||||
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</android.support.design.widget.CoordinatorLayout>
|
</android.support.design.widget.CoordinatorLayout>
|
||||||
|
|
Loading…
Add table
Reference in a new issue