diff options
| author | Robert Berry <robertberry@google.com> | 2018-01-17 14:43:09 +0000 |
|---|---|---|
| committer | Robert Berry <robertberry@google.com> | 2018-01-17 21:32:58 +0000 |
| commit | a16cd59a3438383fb3473af4903b9ada596e5cb0 (patch) | |
| tree | 790796023c58ca624c9b67de631b4f945c9e8497 /core/java | |
| parent | b1a00d5e16fd1b5ebb39e0d462c5216bc453e701 (diff) | |
Create exception hierarchy for RecoveryController
Sets up a sensible exception hierarchy. Consolidates two error codes
that both represented some kind of internal error into a single code.
Fixed some cases where the wrong error codes were used to signal.
Test: adb shell am instrument -w -e package
com.android.server.locksettings.recoverablekeystore
com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
Change-Id: I6b1f97715cdc28a4be79912abb6f48e6657b048b
Diffstat (limited to 'core/java')
8 files changed, 334 insertions, 159 deletions
diff --git a/core/java/android/security/keystore/BadCertificateFormatException.java b/core/java/android/security/keystore/BadCertificateFormatException.java new file mode 100644 index 000000000000..ddc7bd2366ac --- /dev/null +++ b/core/java/android/security/keystore/BadCertificateFormatException.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore; + +/** + * Error thrown when the recovery agent supplies an invalid X509 certificate. + * + * @hide + */ +public class BadCertificateFormatException extends RecoveryControllerException { + public BadCertificateFormatException(String msg) { + super(msg); + } +} diff --git a/core/java/android/security/keystore/DecryptionFailedException.java b/core/java/android/security/keystore/DecryptionFailedException.java new file mode 100644 index 000000000000..945fcf6f88f2 --- /dev/null +++ b/core/java/android/security/keystore/DecryptionFailedException.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore; + +/** + * Error thrown when decryption failed, due to an agent error. i.e., using the incorrect key, + * trying to decrypt garbage data, trying to decrypt data that has somehow been corrupted, etc. + * + * @hide + */ +public class DecryptionFailedException extends RecoveryControllerException { + + public DecryptionFailedException(String msg) { + super(msg); + } +} diff --git a/core/java/android/security/keystore/InternalRecoveryServiceException.java b/core/java/android/security/keystore/InternalRecoveryServiceException.java new file mode 100644 index 000000000000..85829bed9191 --- /dev/null +++ b/core/java/android/security/keystore/InternalRecoveryServiceException.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore; + +/** + * An error thrown when something went wrong internally in the recovery service. + * + * <p>This is an unexpected error, and indicates a problem with the service itself, rather than the + * caller having performed some kind of illegal action. + * + * @hide + */ +public class InternalRecoveryServiceException extends RecoveryControllerException { + public InternalRecoveryServiceException(String msg) { + super(msg); + } + + public InternalRecoveryServiceException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/core/java/android/security/keystore/LockScreenRequiredException.java b/core/java/android/security/keystore/LockScreenRequiredException.java new file mode 100644 index 000000000000..b07fb9cdd002 --- /dev/null +++ b/core/java/android/security/keystore/LockScreenRequiredException.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore; + +/** + * Error thrown when trying to generate keys for a profile that has no lock screen set. + * + * <p>A lock screen must be set, as the lock screen is used to encrypt the snapshot. + * + * @hide + */ +public class LockScreenRequiredException extends RecoveryControllerException { + public LockScreenRequiredException(String msg) { + super(msg); + } +} diff --git a/core/java/android/security/keystore/RecoveryControllerException.java b/core/java/android/security/keystore/RecoveryControllerException.java new file mode 100644 index 000000000000..31fd4af9a7d1 --- /dev/null +++ b/core/java/android/security/keystore/RecoveryControllerException.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore; + +import java.security.GeneralSecurityException; + +/** + * Base exception for errors thrown by {@link RecoveryManager}. + * + * @hide + */ +public abstract class RecoveryControllerException extends GeneralSecurityException { + RecoveryControllerException() { } + + RecoveryControllerException(String msg) { + super(msg); + } + + public RecoveryControllerException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/core/java/android/security/keystore/RecoveryManager.java b/core/java/android/security/keystore/RecoveryManager.java index bddf3e849182..6177cd76bed4 100644 --- a/core/java/android/security/keystore/RecoveryManager.java +++ b/core/java/android/security/keystore/RecoveryManager.java @@ -46,6 +46,52 @@ public class RecoveryManager { /** Key cannot be synced. */ public static final int RECOVERY_STATUS_PERMANENT_FAILURE = 3; + /** + * Failed because no snapshot is yet pending to be synced for the user. + * + * @hide + */ + public static final int ERROR_NO_SNAPSHOT_PENDING = 21; + + /** + * Failed due to an error internal to the recovery service. This is unexpected and indicates + * either a problem with the logic in the service, or a problem with a dependency of the + * service (such as AndroidKeyStore). + * + * @hide + */ + public static final int ERROR_SERVICE_INTERNAL_ERROR = 22; + + /** + * Failed because the user does not have a lock screen set. + * + * @hide + */ + public static final int ERROR_INSECURE_USER = 23; + + /** + * Error thrown when attempting to use a recovery session that has since been closed. + * + * @hide + */ + public static final int ERROR_SESSION_EXPIRED = 24; + + /** + * Failed because the provided certificate was not a valid X509 certificate. + * + * @hide + */ + public static final int ERROR_BAD_CERTIFICATE_FORMAT = 25; + + /** + * Error thrown if decryption failed. This might be because the tag is wrong, the key is wrong, + * the data has become corrupted, the data has been tampered with, etc. + * + * @hide + */ + public static final int ERROR_DECRYPTION_FAILED = 26; + + private final ILockSettings mBinder; private RecoveryManager(ILockSettings binder) { @@ -75,19 +121,22 @@ public class RecoveryManager { * * @param rootCertificateAlias alias of a root certificate preinstalled on the device * @param signedPublicKeyList binary blob a list of X509 certificates and signature - * @throws RecoveryManagerException if signature is invalid, or key rotation was rate - * limited. - * @hide + * @throws BadCertificateFormatException if the {@code signedPublicKeyList} is in a bad format. + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. */ public void initRecoveryService( @NonNull String rootCertificateAlias, @NonNull byte[] signedPublicKeyList) - throws RecoveryManagerException { + throws BadCertificateFormatException, InternalRecoveryServiceException { try { mBinder.initRecoveryService(rootCertificateAlias, signedPublicKeyList); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { - throw RecoveryManagerException.fromServiceSpecificException(e); + if (e.errorCode == ERROR_BAD_CERTIFICATE_FORMAT) { + throw new BadCertificateFormatException(e.getMessage()); + } + throw wrapUnexpectedServiceSpecificException(e); } } @@ -97,17 +146,20 @@ public class RecoveryManager { * * @param account specific to Recovery agent. * @return Data necessary to recover keystore. - * @hide + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. */ - @NonNull public KeychainSnapshot getRecoveryData(@NonNull byte[] account) - throws RecoveryManagerException { + public @NonNull KeychainSnapshot getRecoveryData(@NonNull byte[] account) + throws InternalRecoveryServiceException { try { - KeychainSnapshot keychainSnapshot = mBinder.getRecoveryData(account); - return keychainSnapshot; + return mBinder.getRecoveryData(account); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { - throw RecoveryManagerException.fromServiceSpecificException(e); + if (e.errorCode == ERROR_NO_SNAPSHOT_PENDING) { + return null; + } + throw wrapUnexpectedServiceSpecificException(e); } } @@ -118,16 +170,17 @@ public class RecoveryManager { * * @param intent triggered when new snapshot is available. Unregisters listener if the value is * {@code null}. - * @hide + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. */ public void setSnapshotCreatedPendingIntent(@Nullable PendingIntent intent) - throws RecoveryManagerException { + throws InternalRecoveryServiceException { try { mBinder.setSnapshotCreatedPendingIntent(intent); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { - throw RecoveryManagerException.fromServiceSpecificException(e); + throw wrapUnexpectedServiceSpecificException(e); } } @@ -137,10 +190,11 @@ public class RecoveryManager { * * @return Map from recovery agent accounts to snapshot versions. * @see KeychainSnapshot#getSnapshotVersion - * @hide + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. */ public @NonNull Map<byte[], Integer> getRecoverySnapshotVersions() - throws RecoveryManagerException { + throws InternalRecoveryServiceException { try { // IPC doesn't support generic Maps. @SuppressWarnings("unchecked") @@ -150,7 +204,7 @@ public class RecoveryManager { } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { - throw RecoveryManagerException.fromServiceSpecificException(e); + throw wrapUnexpectedServiceSpecificException(e); } } @@ -161,16 +215,16 @@ public class RecoveryManager { * * @param serverParams included in recovery key blob. * @see #getRecoveryData - * @throws RecoveryManagerException If parameters rotation is rate limited. - * @hide + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. */ - public void setServerParams(byte[] serverParams) throws RecoveryManagerException { + public void setServerParams(byte[] serverParams) throws InternalRecoveryServiceException { try { mBinder.setServerParams(serverParams); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { - throw RecoveryManagerException.fromServiceSpecificException(e); + throw wrapUnexpectedServiceSpecificException(e); } } @@ -183,16 +237,18 @@ public class RecoveryManager { * @param aliases List of application-specific key aliases. If the array is empty, updates the * status for all existing recoverable keys. * @param status Status specific to recovery agent. + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. */ public void setRecoveryStatus( @NonNull String packageName, @Nullable String[] aliases, int status) - throws NameNotFoundException, RecoveryManagerException { + throws NameNotFoundException, InternalRecoveryServiceException { try { mBinder.setRecoveryStatus(packageName, aliases, status); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { - throw RecoveryManagerException.fromServiceSpecificException(e); + throw wrapUnexpectedServiceSpecificException(e); } } @@ -209,10 +265,10 @@ public class RecoveryManager { * * @return {@code Map} from KeyStore alias to recovery status. * @see #setRecoveryStatus - * @hide + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. */ - public Map<String, Integer> getRecoveryStatus() - throws RecoveryManagerException { + public Map<String, Integer> getRecoveryStatus() throws InternalRecoveryServiceException { try { // IPC doesn't support generic Maps. @SuppressWarnings("unchecked") @@ -222,7 +278,7 @@ public class RecoveryManager { } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { - throw RecoveryManagerException.fromServiceSpecificException(e); + throw wrapUnexpectedServiceSpecificException(e); } } @@ -232,16 +288,18 @@ public class RecoveryManager { * * @param secretTypes {@link KeychainProtectionParameter#TYPE_LOCKSCREEN} or {@link * KeychainProtectionParameter#TYPE_CUSTOM_PASSWORD} + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. */ public void setRecoverySecretTypes( @NonNull @KeychainProtectionParameter.UserSecretType int[] secretTypes) - throws RecoveryManagerException { + throws InternalRecoveryServiceException { try { mBinder.setRecoverySecretTypes(secretTypes); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { - throw RecoveryManagerException.fromServiceSpecificException(e); + throw wrapUnexpectedServiceSpecificException(e); } } @@ -251,15 +309,17 @@ public class RecoveryManager { * * @return list of recovery secret types * @see KeychainSnapshot + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. */ - @NonNull public @KeychainProtectionParameter.UserSecretType int[] getRecoverySecretTypes() - throws RecoveryManagerException { + public @NonNull @KeychainProtectionParameter.UserSecretType int[] getRecoverySecretTypes() + throws InternalRecoveryServiceException { try { return mBinder.getRecoverySecretTypes(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { - throw RecoveryManagerException.fromServiceSpecificException(e); + throw wrapUnexpectedServiceSpecificException(e); } } @@ -269,17 +329,18 @@ public class RecoveryManager { * called. * * @return list of recovery secret types - * @hide + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. */ @NonNull public @KeychainProtectionParameter.UserSecretType int[] getPendingRecoverySecretTypes() - throws RecoveryManagerException { + throws InternalRecoveryServiceException { try { return mBinder.getPendingRecoverySecretTypes(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { - throw RecoveryManagerException.fromServiceSpecificException(e); + throw wrapUnexpectedServiceSpecificException(e); } } @@ -291,16 +352,17 @@ public class RecoveryManager { * * @param recoverySecret user generated secret together with parameters necessary to regenerate * it on a new device. - * @hide + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. */ public void recoverySecretAvailable(@NonNull KeychainProtectionParameter recoverySecret) - throws RecoveryManagerException { + throws InternalRecoveryServiceException { try { mBinder.recoverySecretAvailable(recoverySecret); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { - throw RecoveryManagerException.fromServiceSpecificException(e); + throw wrapUnexpectedServiceSpecificException(e); } } @@ -321,6 +383,10 @@ public class RecoveryManager { * @return Binary blob with recovery claim. It is encrypted with verifierPublicKey and contains * a proof of user secrets, session symmetric key and parameters necessary to identify the * counter with the number of failed recovery attempts. + * @throws BadCertificateFormatException if the {@code verifierPublicKey} is in an incorrect + * format. + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. */ public @NonNull byte[] startRecoverySession( @NonNull String sessionId, @@ -328,7 +394,7 @@ public class RecoveryManager { @NonNull byte[] vaultParams, @NonNull byte[] vaultChallenge, @NonNull List<KeychainProtectionParameter> secrets) - throws RecoveryManagerException { + throws BadCertificateFormatException, InternalRecoveryServiceException { try { byte[] recoveryClaim = mBinder.startRecoverySession( @@ -341,7 +407,10 @@ public class RecoveryManager { } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { - throw RecoveryManagerException.fromServiceSpecificException(e); + if (e.errorCode == ERROR_BAD_CERTIFICATE_FORMAT) { + throw new BadCertificateFormatException(e.getMessage()); + } + throw wrapUnexpectedServiceSpecificException(e); } } @@ -355,19 +424,29 @@ public class RecoveryManager { * and session. KeyStore only uses package names from the application info in {@link * WrappedApplicationKey}. Caller is responsibility to perform certificates check. * @return Map from alias to raw key material. + * @throws SessionExpiredException if {@code session} has since been closed. + * @throws DecryptionFailedException if unable to decrypt the snapshot. + * @throws InternalRecoveryServiceException if an error occurs internal to the recovery service. */ public Map<String, byte[]> recoverKeys( @NonNull String sessionId, @NonNull byte[] recoveryKeyBlob, @NonNull List<WrappedApplicationKey> applicationKeys) - throws RecoveryManagerException { + throws SessionExpiredException, DecryptionFailedException, + InternalRecoveryServiceException { try { return (Map<String, byte[]>) mBinder.recoverKeys( sessionId, recoveryKeyBlob, applicationKeys); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { - throw RecoveryManagerException.fromServiceSpecificException(e); + if (e.errorCode == ERROR_DECRYPTION_FAILED) { + throw new DecryptionFailedException(e.getMessage()); + } + if (e.errorCode == ERROR_SESSION_EXPIRED) { + throw new SessionExpiredException(e.getMessage()); + } + throw wrapUnexpectedServiceSpecificException(e); } } @@ -376,17 +455,23 @@ public class RecoveryManager { * raw material of the key. * * @param alias The key alias. - * @throws RecoveryManagerException if an error occurred generating and storing the - * key. + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + * @throws LockScreenRequiredException if the user has not set a lock screen. This is required + * to generate recoverable keys, as the snapshots are encrypted using a key derived from the + * lock screen. */ public byte[] generateAndStoreKey(@NonNull String alias) - throws RecoveryManagerException { + throws InternalRecoveryServiceException, LockScreenRequiredException { try { return mBinder.generateAndStoreKey(alias); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { - throw RecoveryManagerException.fromServiceSpecificException(e); + if (e.errorCode == ERROR_INSECURE_USER) { + throw new LockScreenRequiredException(e.getMessage()); + } + throw wrapUnexpectedServiceSpecificException(e); } } @@ -394,14 +479,28 @@ public class RecoveryManager { * Removes a key called {@code alias} from the recoverable key store. * * @param alias The key alias. + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. */ - public void removeKey(@NonNull String alias) throws RecoveryManagerException { + public void removeKey(@NonNull String alias) throws InternalRecoveryServiceException { try { mBinder.removeKey(alias); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { - throw RecoveryManagerException.fromServiceSpecificException(e); + throw wrapUnexpectedServiceSpecificException(e); } } + + private InternalRecoveryServiceException wrapUnexpectedServiceSpecificException( + ServiceSpecificException e) { + if (e.errorCode == ERROR_SERVICE_INTERNAL_ERROR) { + return new InternalRecoveryServiceException(e.getMessage()); + } + + // Should never happen. If it does, it's a bug, and we need to update how the method that + // called this throws its exceptions. + return new InternalRecoveryServiceException("Unexpected error code for method: " + + e.errorCode, e); + } } diff --git a/core/java/android/security/keystore/RecoveryManagerException.java b/core/java/android/security/keystore/RecoveryManagerException.java deleted file mode 100644 index 344718aa31d4..000000000000 --- a/core/java/android/security/keystore/RecoveryManagerException.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.security.keystore; - -import android.os.ServiceSpecificException; - -/** - * Exception thrown by {@link RecoveryManager} methods. - * - * @hide - */ -public class RecoveryManagerException extends Exception { - /** - * Failed because the loader has not been initialized with a recovery public key yet. - */ - public static final int ERROR_UNINITIALIZED_RECOVERY_PUBLIC_KEY = 20; - - /** - * Failed because no snapshot is yet pending to be synced for the user. - */ - public static final int ERROR_NO_SNAPSHOT_PENDING = 21; - - /** - * Failed due to an error internal to AndroidKeyStore. - */ - public static final int ERROR_KEYSTORE_INTERNAL_ERROR = 22; - - /** - * Failed because the user does not have a lock screen set. - */ - public static final int ERROR_INSECURE_USER = 24; - - /** - * Failed because of an internal database error. - */ - public static final int ERROR_DATABASE_ERROR = 25; - - /** - * Failed because the provided certificate was not a valid X509 certificate. - */ - public static final int ERROR_BAD_X509_CERTIFICATE = 26; - - /** - * Should never be thrown - some algorithm that all AOSP implementations must support is - * not available. - */ - public static final int ERROR_UNEXPECTED_MISSING_ALGORITHM = 27; - - /** - * Error thrown if decryption failed. This might be because the tag is wrong, the key is wrong, - * the data has become corrupted, the data has been tampered with, etc. - */ - public static final int ERROR_DECRYPTION_FAILED = 28; - - /** - * Rate limit is enforced to prevent using too many trusted remote devices, since each device - * can have its own number of user secret guesses allowed. - * - * @hide - */ - public static final int ERROR_RATE_LIMIT_EXCEEDED = 29; - - private int mErrorCode; - - /** - * Creates new {@link #RecoveryManagerException} instance from the error code. - * - * @param errorCode An error code, as listed at the top of this file. - * @param message The associated error message. - * @hide - */ - public static RecoveryManagerException fromErrorCode( - int errorCode, String message) { - return new RecoveryManagerException(errorCode, message); - } - /** - * Creates new {@link #RecoveryManagerException} from {@link - * ServiceSpecificException}. - * - * @param e exception thrown on service side. - * @hide - */ - static RecoveryManagerException fromServiceSpecificException( - ServiceSpecificException e) throws RecoveryManagerException { - throw RecoveryManagerException.fromErrorCode(e.errorCode, e.getMessage()); - } - - private RecoveryManagerException(int errorCode, String message) { - super(message); - mErrorCode = errorCode; - } - - /** Returns errorCode. */ - public int getErrorCode() { - return mErrorCode; - } -} diff --git a/core/java/android/security/keystore/SessionExpiredException.java b/core/java/android/security/keystore/SessionExpiredException.java new file mode 100644 index 000000000000..f13e20602625 --- /dev/null +++ b/core/java/android/security/keystore/SessionExpiredException.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore; + +/** + * Error thrown when attempting to use a {@link RecoverySession} that has since expired. + * + * @hide + */ +public class SessionExpiredException extends RecoveryControllerException { + public SessionExpiredException(String msg) { + super(msg); + } +} |
