diff options
7 files changed, 38 insertions, 13 deletions
diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java index 70054fc2d71e..000b8f300dd0 100644 --- a/core/java/android/security/keystore/recovery/RecoveryController.java +++ b/core/java/android/security/keystore/recovery/RecoveryController.java @@ -29,6 +29,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; @@ -635,7 +636,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) { @@ -666,7 +667,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) { @@ -696,6 +697,8 @@ public class RecoveryController { return getKeyFromGrant(grantAlias); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } catch (KeyPermanentlyInvalidatedException | UnrecoverableKeyException e) { + throw new UnrecoverableKeyException("Failed to get key from keystore"); } catch (ServiceSpecificException e) { throw wrapUnexpectedServiceSpecificException(e); } @@ -704,7 +707,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 3bb64219cdca..662271281085 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; @@ -218,7 +219,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 030fa60abfd3..6155ae4f52b1 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; @@ -538,7 +539,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 25a6cdc4a7f4..330d24da3e32 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -97,6 +97,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; @@ -1188,6 +1191,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 |