diff options
7 files changed, 40 insertions, 15 deletions
diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java index c43a6668b9c3..a88aa8cb4401 100644 --- a/core/java/android/security/keystore/recovery/RecoveryController.java +++ b/core/java/android/security/keystore/recovery/RecoveryController.java @@ -28,6 +28,7 @@ import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.security.KeyStore; import android.security.keystore.AndroidKeyStoreProvider; +import android.security.keystore.KeyPermanentlyInvalidatedException; import com.android.internal.widget.ILockSettings; @@ -548,7 +549,7 @@ public class RecoveryController { return getKeyFromGrant(grantAlias); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); - } catch (UnrecoverableKeyException e) { + } catch (KeyPermanentlyInvalidatedException | UnrecoverableKeyException e) { throw new InternalRecoveryServiceException("Failed to get key from keystore", e); } catch (ServiceSpecificException e) { if (e.errorCode == ERROR_INSECURE_USER) { @@ -589,7 +590,7 @@ public class RecoveryController { return getKeyFromGrant(grantAlias); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); - } catch (UnrecoverableKeyException e) { + } catch (KeyPermanentlyInvalidatedException | UnrecoverableKeyException e) { throw new InternalRecoveryServiceException("Failed to get key from keystore", e); } catch (ServiceSpecificException e) { if (e.errorCode == ERROR_INSECURE_USER) { @@ -622,7 +623,7 @@ public class RecoveryController { return getKeyFromGrant(grantAlias); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); - } catch (UnrecoverableKeyException e) { + } catch (KeyPermanentlyInvalidatedException | UnrecoverableKeyException e) { throw new InternalRecoveryServiceException("Failed to get key from keystore", e); } catch (ServiceSpecificException e) { if (e.errorCode == ERROR_INSECURE_USER) { @@ -665,7 +666,7 @@ public class RecoveryController { return getKeyFromGrant(grantAlias); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); - } catch (UnrecoverableKeyException e) { + } catch (KeyPermanentlyInvalidatedException | UnrecoverableKeyException e) { throw new InternalRecoveryServiceException("Failed to get key from keystore", e); } catch (ServiceSpecificException e) { if (e.errorCode == ERROR_INSECURE_USER) { @@ -695,6 +696,8 @@ public class RecoveryController { return getKeyFromGrant(grantAlias); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } catch (KeyPermanentlyInvalidatedException | UnrecoverableKeyException e) { + throw new UnrecoverableKeyException(e.getMessage()); } catch (ServiceSpecificException e) { throw wrapUnexpectedServiceSpecificException(e); } @@ -703,7 +706,8 @@ public class RecoveryController { /** * Returns the key with the given {@code grantAlias}. */ - @NonNull Key getKeyFromGrant(@NonNull String grantAlias) throws UnrecoverableKeyException { + @NonNull Key getKeyFromGrant(@NonNull String grantAlias) + throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore( mKeyStore, grantAlias, diff --git a/core/java/android/security/keystore/recovery/RecoverySession.java b/core/java/android/security/keystore/recovery/RecoverySession.java index 42e718268d2d..2b2438ad2e11 100644 --- a/core/java/android/security/keystore/recovery/RecoverySession.java +++ b/core/java/android/security/keystore/recovery/RecoverySession.java @@ -22,6 +22,7 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.os.RemoteException; import android.os.ServiceSpecificException; +import android.security.keystore.KeyPermanentlyInvalidatedException; import android.util.ArrayMap; import android.util.Log; @@ -174,7 +175,7 @@ public class RecoverySession implements AutoCloseable { Key key; try { key = mRecoveryController.getKeyFromGrant(grantAlias); - } catch (UnrecoverableKeyException e) { + } catch (KeyPermanentlyInvalidatedException | UnrecoverableKeyException e) { throw new InternalRecoveryServiceException( String.format( Locale.US, diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index 5d5e40fd3ac3..c180197d6f84 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -36,6 +36,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.security.keystore.AndroidKeyStoreProvider; +import android.security.keystore.KeyPermanentlyInvalidatedException; import android.security.keystore.KeyProperties; import java.io.ByteArrayInputStream; @@ -584,7 +585,7 @@ public final class KeyChain { try { return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore( KeyStore.getInstance(), keyId, KeyStore.UID_SELF); - } catch (RuntimeException | UnrecoverableKeyException e) { + } catch (RuntimeException | UnrecoverableKeyException | KeyPermanentlyInvalidatedException e) { throw new KeyChainException(e); } } diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 213ed7d1ff0a..bfce17c3e6ab 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -98,6 +98,9 @@ public class KeyStore { */ public static final int OP_AUTH_NEEDED = 15; + // Used when a user changes their pin, invalidating old auth bound keys. + public static final int KEY_PERMANENTLY_INVALIDATED = 17; + // Used for UID field to indicate the calling UID. public static final int UID_SELF = -1; @@ -1200,6 +1203,8 @@ public class KeyStore { return new KeyStoreException(errorCode, "Key blob corrupted"); case OP_AUTH_NEEDED: return new KeyStoreException(errorCode, "Operation requires authorization"); + case KEY_PERMANENTLY_INVALIDATED: + return new KeyStoreException(errorCode, "Key permanently invalidated"); default: return new KeyStoreException(errorCode, String.valueOf(errorCode)); } diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java index d44c894fa573..91aac8367976 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -526,7 +526,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato + result.getPrivate().getAlgorithm() + " vs " + mJcaKeyAlgorithm); } return result; - } catch (UnrecoverableKeyException e) { + } catch (UnrecoverableKeyException | KeyPermanentlyInvalidatedException e) { throw new ProviderException("Failed to load generated key pair from keystore", e); } } diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java index c7c9ee4a406a..234615d9c81d 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java @@ -228,10 +228,16 @@ public class AndroidKeyStoreProvider extends Provider { @NonNull private static KeyCharacteristics getKeyCharacteristics(@NonNull KeyStore keyStore, @NonNull String alias, int uid) - throws UnrecoverableKeyException { + throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { KeyCharacteristics keyCharacteristics = new KeyCharacteristics(); int errorCode = keyStore.getKeyCharacteristics( alias, null, null, uid, keyCharacteristics); + if (errorCode == KeyStore.KEY_PERMANENTLY_INVALIDATED) { + throw (KeyPermanentlyInvalidatedException) + new KeyPermanentlyInvalidatedException( + "User changed or deleted their auth credentials", + KeyStore.getKeyStoreException(errorCode)); + } if (errorCode != KeyStore.NO_ERROR) { throw (UnrecoverableKeyException) new UnrecoverableKeyException("Failed to obtain information about key") @@ -276,7 +282,7 @@ public class AndroidKeyStoreProvider extends Provider { @NonNull public static AndroidKeyStorePublicKey loadAndroidKeyStorePublicKeyFromKeystore( @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid) - throws UnrecoverableKeyException { + throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { return loadAndroidKeyStorePublicKeyFromKeystore(keyStore, privateKeyAlias, uid, getKeyCharacteristics(keyStore, privateKeyAlias, uid)); } @@ -297,7 +303,7 @@ public class AndroidKeyStoreProvider extends Provider { @NonNull public static KeyPair loadAndroidKeyStoreKeyPairFromKeystore( @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid) - throws UnrecoverableKeyException { + throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { return loadAndroidKeyStoreKeyPairFromKeystore(keyStore, privateKeyAlias, uid, getKeyCharacteristics(keyStore, privateKeyAlias, uid)); } @@ -315,7 +321,7 @@ public class AndroidKeyStoreProvider extends Provider { @NonNull public static AndroidKeyStorePrivateKey loadAndroidKeyStorePrivateKeyFromKeystore( @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid) - throws UnrecoverableKeyException { + throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { return loadAndroidKeyStorePrivateKeyFromKeystore(keyStore, privateKeyAlias, uid, getKeyCharacteristics(keyStore, privateKeyAlias, uid)); } @@ -354,7 +360,7 @@ public class AndroidKeyStoreProvider extends Provider { @NonNull public static AndroidKeyStoreKey loadAndroidKeyStoreKeyFromKeystore( @NonNull KeyStore keyStore, @NonNull String userKeyAlias, int uid) - throws UnrecoverableKeyException { + throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { KeyCharacteristics keyCharacteristics = getKeyCharacteristics(keyStore, userKeyAlias, uid); Integer keymasterAlgorithm = keyCharacteristics.getEnum(KeymasterDefs.KM_TAG_ALGORITHM); diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java index 4c007cb70ba2..105af6e829f8 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java @@ -24,6 +24,7 @@ import android.security.KeyStoreParameter; import android.security.keymaster.KeyCharacteristics; import android.security.keymaster.KeymasterArguments; import android.security.keymaster.KeymasterDefs; +import android.security.keystore.KeyPermanentlyInvalidatedException; import android.security.keystore.KeyProperties; import android.security.keystore.KeyProtection; import android.security.keystore.SecureKeyImportUnavailableException; @@ -93,13 +94,20 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException { String userKeyAlias = Credentials.USER_PRIVATE_KEY + alias; + AndroidKeyStoreKey key; if (!mKeyStore.contains(userKeyAlias, mUid)) { // try legacy prefix for backward compatibility userKeyAlias = Credentials.USER_SECRET_KEY + alias; if (!mKeyStore.contains(userKeyAlias, mUid)) return null; } - return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(mKeyStore, userKeyAlias, - mUid); + try { + key = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(mKeyStore, + userKeyAlias, + mUid); + } catch (KeyPermanentlyInvalidatedException e) { + throw new UnrecoverableKeyException(e.getMessage()); + } + return key; } @Override |