Fix a crash on Kitkat. It doesn't like the KeyStoreHandle class for some reason

This commit is contained in:
Alexander Bakker 2018-02-13 19:27:40 +01:00
parent 3a3e4cc584
commit 6e68d79816
5 changed files with 57 additions and 29 deletions

View file

@ -7,10 +7,12 @@ import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import me.impy.aegis.crypto.KeyStoreHandle; import me.impy.aegis.crypto.KeyStoreHandle;
import me.impy.aegis.crypto.KeyStoreHandleException;
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;
import me.impy.aegis.crypto.slots.Slot; import me.impy.aegis.crypto.slots.Slot;
import me.impy.aegis.helpers.FingerprintHelper;
public class SlotHolder extends RecyclerView.ViewHolder { public class SlotHolder extends RecyclerView.ViewHolder {
private TextView _slotUsed; private TextView _slotUsed;
@ -35,12 +37,14 @@ public class SlotHolder extends RecyclerView.ViewHolder {
} else if (slot instanceof FingerprintSlot) { } else if (slot instanceof FingerprintSlot) {
_slotName.setText("Finger"); _slotName.setText("Finger");
_slotImg.setImageResource(R.drawable.ic_fingerprint_black_24dp); _slotImg.setImageResource(R.drawable.ic_fingerprint_black_24dp);
if (FingerprintHelper.isSupported()) {
try { try {
KeyStoreHandle keyStore = new KeyStoreHandle(); KeyStoreHandle keyStore = new KeyStoreHandle();
if (keyStore.containsKey(slot.getID())) { if (keyStore.containsKey(slot.getID())) {
_slotUsed.setVisibility(View.VISIBLE); _slotUsed.setVisibility(View.VISIBLE);
} }
} catch (Exception e) { } } catch (KeyStoreHandleException e) { }
}
} else if (slot instanceof RawSlot) { } else if (slot instanceof RawSlot) {
_slotName.setText("Raw"); _slotName.setText("Raw");
_slotImg.setImageResource(R.drawable.ic_vpn_key_black_24dp); _slotImg.setImageResource(R.drawable.ic_vpn_key_black_24dp);

View file

@ -1,6 +1,7 @@
package me.impy.aegis; package me.impy.aegis;
import android.content.Intent; import android.content.Intent;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
@ -9,12 +10,12 @@ import android.support.v7.widget.RecyclerView;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.EditText;
import android.widget.Toast; import android.widget.Toast;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import me.impy.aegis.crypto.KeyStoreHandle; import me.impy.aegis.crypto.KeyStoreHandle;
import me.impy.aegis.crypto.KeyStoreHandleException;
import me.impy.aegis.crypto.MasterKey; import me.impy.aegis.crypto.MasterKey;
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;
@ -70,6 +71,7 @@ public class SlotManagerActivity extends AegisActivity implements SlotAdapter.Li
// only show the fingerprint option if we can get an instance of the fingerprint manager // only show the fingerprint option if we can get an instance of the fingerprint manager
// and if none of the slots in the collection has a matching alias in the keystore // and if none of the slots in the collection has a matching alias in the keystore
int visibility = View.VISIBLE; int visibility = View.VISIBLE;
if (FingerprintHelper.isSupported()) {
try { try {
KeyStoreHandle keyStore = new KeyStoreHandle(); KeyStoreHandle keyStore = new KeyStoreHandle();
for (FingerprintSlot slot : _slots.findAll(FingerprintSlot.class)) { for (FingerprintSlot slot : _slots.findAll(FingerprintSlot.class)) {
@ -78,7 +80,10 @@ public class SlotManagerActivity extends AegisActivity implements SlotAdapter.Li
break; break;
} }
} }
} catch (Exception e) { } catch (KeyStoreHandleException e) {
visibility = View.GONE;
}
} else {
visibility = View.GONE; visibility = View.GONE;
} }
findViewById(R.id.button_add_fingerprint).setVisibility(visibility); findViewById(R.id.button_add_fingerprint).setVisibility(visibility);

View file

@ -19,23 +19,29 @@ import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException; import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import me.impy.aegis.crypto.slots.FingerprintSlot;
public class KeyStoreHandle { public class KeyStoreHandle {
private final KeyStore _keyStore; private final KeyStore _keyStore;
private static final String STORE_NAME = "AndroidKeyStore"; private static final String STORE_NAME = "AndroidKeyStore";
public KeyStoreHandle() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { public KeyStoreHandle() throws KeyStoreHandleException {
try {
_keyStore = KeyStore.getInstance(STORE_NAME); _keyStore = KeyStore.getInstance(STORE_NAME);
_keyStore.load(null); _keyStore.load(null);
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) {
throw new KeyStoreHandleException(e);
}
} }
public boolean containsKey(String id) throws KeyStoreException { public boolean containsKey(String id) throws KeyStoreHandleException {
try {
return _keyStore.containsAlias(id); return _keyStore.containsAlias(id);
} catch (KeyStoreException e) {
throw new KeyStoreHandleException(e);
}
} }
public SecretKey generateKey(String id) throws Exception { public SecretKey generateKey(String id) throws Exception {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (isSupported()) {
KeyGenerator generator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, STORE_NAME); KeyGenerator generator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, STORE_NAME);
generator.init(new KeyGenParameterSpec.Builder(id, generator.init(new KeyGenParameterSpec.Builder(id,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
@ -58,7 +64,7 @@ public class KeyStoreHandle {
// try to initialize a dummy cipher // try to initialize a dummy cipher
// and see if KeyPermanentlyInvalidatedException is thrown // and see if KeyPermanentlyInvalidatedException is thrown
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (isSupported()) {
try { try {
@SuppressLint("GetInstance") @SuppressLint("GetInstance")
Cipher cipher = Cipher.getInstance(CryptoUtils.CRYPTO_CIPHER_RAW); Cipher cipher = Cipher.getInstance(CryptoUtils.CRYPTO_CIPHER_RAW);
@ -76,4 +82,8 @@ public class KeyStoreHandle {
public void deleteKey(String id) throws KeyStoreException { public void deleteKey(String id) throws KeyStoreException {
_keyStore.deleteEntry(id); _keyStore.deleteEntry(id);
} }
public static boolean isSupported() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
} }

View file

@ -0,0 +1,7 @@
package me.impy.aegis.crypto;
public class KeyStoreHandleException extends Exception {
public KeyStoreHandleException(Throwable cause) {
super(cause);
}
}

View file

@ -11,14 +11,16 @@ public class FingerprintHelper {
} }
public static FingerprintManager getManager(Context context) { public static FingerprintManager getManager(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (isSupported() && PermissionHelper.granted(context, Manifest.permission.USE_FINGERPRINT)) {
if (PermissionHelper.granted(context, Manifest.permission.USE_FINGERPRINT)) {
FingerprintManager manager = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE); FingerprintManager manager = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
if (manager != null && manager.isHardwareDetected() && manager.hasEnrolledFingerprints()) { if (manager != null && manager.isHardwareDetected() && manager.hasEnrolledFingerprints()) {
return manager; return manager;
} }
} }
}
return null; return null;
} }
public static boolean isSupported() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
} }