* limitations under the License.
*/
-package android.security.recoverablekeystore;
+package android.security.keystore;
/* @hide */
-parcelable KeyStoreRecoveryData;
+parcelable EntryRecoveryData;
--- /dev/null
+/*
+ * 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.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Helper class with data necessary recover a single application key, given a recovery key.
+ *
+ * <ul>
+ * <li>Alias - Keystore alias of the key.
+ * <li>Encrypted key material.
+ * </ul>
+ *
+ * Note that Application info is not included. Recovery Agent can only make its own keys
+ * recoverable.
+ *
+ * @hide
+ */
+public final class EntryRecoveryData implements Parcelable {
+ private String mAlias;
+ // The only supported format is AES-256 symmetric key.
+ private byte[] mEncryptedKeyMaterial;
+
+ /**
+ * Builder for creating {@link EntryRecoveryData}.
+ */
+ public static class Builder {
+ private EntryRecoveryData mInstance = new EntryRecoveryData();
+
+ /**
+ * Sets Application-specific alias of the key.
+ *
+ * @param alias The alias.
+ * @return This builder.
+ */
+ public Builder setAlias(@NonNull String alias) {
+ mInstance.mAlias = alias;
+ return this;
+ }
+
+ /**
+ * Sets key material encrypted by recovery key.
+ *
+ * @param encryptedKeyMaterial The key material
+ * @return This builder
+ */
+
+ public Builder setEncryptedKeyMaterial(@NonNull byte[] encryptedKeyMaterial) {
+ mInstance.mEncryptedKeyMaterial = encryptedKeyMaterial;
+ return this;
+ }
+
+ /**
+ * Creates a new {@link EntryRecoveryData} instance.
+ *
+ * @return new instance
+ * @throws NullPointerException if some required fields were not set.
+ */
+ public @NonNull EntryRecoveryData build() {
+ Preconditions.checkNotNull(mInstance.mAlias);
+ Preconditions.checkNotNull(mInstance.mEncryptedKeyMaterial);
+ return mInstance;
+ }
+ }
+
+ private EntryRecoveryData() {
+
+ }
+
+ /**
+ * Deprecated - consider using Builder.
+ * @hide
+ */
+ public EntryRecoveryData(@NonNull String alias, @NonNull byte[] encryptedKeyMaterial) {
+ mAlias = Preconditions.checkNotNull(alias);
+ mEncryptedKeyMaterial = Preconditions.checkNotNull(encryptedKeyMaterial);
+ }
+
+ /**
+ * Application-specific alias of the key.
+ *
+ * @see java.security.KeyStore.aliases
+ */
+ public @NonNull String getAlias() {
+ return mAlias;
+ }
+
+ /** Key material encrypted by recovery key. */
+ public @NonNull byte[] getEncryptedKeyMaterial() {
+ return mEncryptedKeyMaterial;
+ }
+
+ public static final Parcelable.Creator<EntryRecoveryData> CREATOR =
+ new Parcelable.Creator<EntryRecoveryData>() {
+ public EntryRecoveryData createFromParcel(Parcel in) {
+ return new EntryRecoveryData(in);
+ }
+
+ public EntryRecoveryData[] newArray(int length) {
+ return new EntryRecoveryData[length];
+ }
+ };
+
+ /**
+ * @hide
+ */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mAlias);
+ out.writeByteArray(mEncryptedKeyMaterial);
+ }
+
+ /**
+ * @hide
+ */
+ protected EntryRecoveryData(Parcel in) {
+ mAlias = in.readString();
+ mEncryptedKeyMaterial = in.createByteArray();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
* limitations under the License.
*/
-package android.security.recoverablekeystore;
+package android.security.keystore;
/* @hide */
parcelable KeyDerivationParameters;
* limitations under the License.
*/
-package android.security.recoverablekeystore;
+package android.security.keystore;
import android.annotation.IntDef;
import android.annotation.NonNull;
/**
* Salted SHA256
+ * @hide
*/
public static final int ALGORITHM_SHA256 = 1;
/**
* Argon2ID
+ * @hide
*/
// TODO: add Argon2ID support.
public static final int ALGORITHM_ARGON2ID = 2;
}
};
+ /**
+ * @hide
+ */
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mAlgorithm);
out.writeByteArray(mSalt);
}
+ /**
+ * @hide
+ */
protected KeyDerivationParameters(Parcel in) {
mAlgorithm = in.readInt();
mSalt = in.createByteArray();
* limitations under the License.
*/
-package android.security.recoverablekeystore;
+package android.security.keystore;
/* @hide */
-parcelable KeyEntryRecoveryData;
+parcelable RecoveryData;
--- /dev/null
+/*
+ * 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.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.List;
+
+/**
+ * Helper class which returns data necessary to recover keys.
+ * Contains
+ *
+ * <ul>
+ * <li>Snapshot version.
+ * <li>Recovery metadata with UI and key derivation parameters.
+ * <li>List of application keys encrypted by recovery key.
+ * <li>Encrypted recovery key.
+ * </ul>
+ *
+ * @hide
+ */
+public final class RecoveryData implements Parcelable {
+ private Integer mSnapshotVersion;
+ private List<RecoveryMetadata> mRecoveryMetadata;
+ private List<EntryRecoveryData> mEntryRecoveryData;
+ private byte[] mEncryptedRecoveryKeyBlob;
+
+ /**
+ * @hide
+ * Deprecated, consider using builder.
+ */
+ public RecoveryData(
+ int snapshotVersion,
+ @NonNull List<RecoveryMetadata> recoveryMetadata,
+ @NonNull List<EntryRecoveryData> entryRecoveryData,
+ @NonNull byte[] encryptedRecoveryKeyBlob) {
+ mSnapshotVersion = snapshotVersion;
+ mRecoveryMetadata =
+ Preconditions.checkCollectionElementsNotNull(recoveryMetadata, "recoveryMetadata");
+ mEntryRecoveryData = Preconditions.checkCollectionElementsNotNull(entryRecoveryData,
+ "entryRecoveryData");
+ mEncryptedRecoveryKeyBlob = Preconditions.checkNotNull(encryptedRecoveryKeyBlob);
+ }
+
+ private RecoveryData() {
+
+ }
+
+ /**
+ * Snapshot version for given account. It is incremented when user secret or list of application
+ * keys changes.
+ */
+ public int getSnapshotVersion() {
+ return mSnapshotVersion;
+ }
+
+ /**
+ * UI and key derivation parameters. Note that combination of secrets may be used.
+ */
+ public @NonNull List<RecoveryMetadata> getRecoveryMetadata() {
+ return mRecoveryMetadata;
+ }
+
+ /**
+ * List of application keys, with key material encrypted by
+ * the recovery key ({@link #getEncryptedRecoveryKeyBlob}).
+ */
+ public @NonNull List<EntryRecoveryData> getEntryRecoveryData() {
+ return mEntryRecoveryData;
+ }
+
+ /**
+ * Recovery key blob, encrypted by user secret and recovery service public key.
+ */
+ public @NonNull byte[] getEncryptedRecoveryKeyBlob() {
+ return mEncryptedRecoveryKeyBlob;
+ }
+
+ public static final Parcelable.Creator<RecoveryData> CREATOR =
+ new Parcelable.Creator<RecoveryData>() {
+ public RecoveryData createFromParcel(Parcel in) {
+ return new RecoveryData(in);
+ }
+
+ public RecoveryData[] newArray(int length) {
+ return new RecoveryData[length];
+ }
+ };
+
+ /**
+ * Builder for creating {@link RecoveryData}.
+ */
+ public static class Builder {
+ private RecoveryData mInstance = new RecoveryData();
+
+ /**
+ * Snapshot version for given account.
+ *
+ * @param snapshotVersion The snapshot version
+ * @return This builder.
+ */
+ public Builder setSnapshotVersion(int snapshotVersion) {
+ mInstance.mSnapshotVersion = snapshotVersion;
+ return this;
+ }
+
+ /**
+ * Sets UI and key derivation parameters
+ *
+ * @param recoveryMetadata The UI and key derivation parameters
+ * @return This builder.
+ */
+ public Builder setRecoveryMetadata(@NonNull List<RecoveryMetadata> recoveryMetadata) {
+ mInstance.mRecoveryMetadata = recoveryMetadata;
+ return this;
+ }
+
+ /**
+ * List of application keys.
+ *
+ * @param entryRecoveryData List of application keys
+ * @return This builder.
+ */
+ public Builder setEntryRecoveryData(List<EntryRecoveryData> entryRecoveryData) {
+ mInstance.mEntryRecoveryData = entryRecoveryData;
+ return this;
+ }
+
+ /**
+ * Sets recovery key blob
+ *
+ * @param encryptedRecoveryKeyBlob The recovery key blob.
+ * @return This builder.
+ */
+ public Builder setEncryptedRecoveryKeyBlob(@NonNull byte[] encryptedRecoveryKeyBlob) {
+ mInstance.mEncryptedRecoveryKeyBlob = encryptedRecoveryKeyBlob;
+ return this;
+ }
+
+
+ /**
+ * Creates a new {@link RecoveryData} instance.
+ *
+ * @return new instance
+ * @throws NullPointerException if some required fields were not set.
+ */
+ public @NonNull RecoveryData build() {
+ Preconditions.checkNotNull(mInstance.mSnapshotVersion);
+ Preconditions.checkCollectionElementsNotNull(mInstance.mRecoveryMetadata,
+ "recoveryMetadata");
+ Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData,
+ "entryRecoveryData");
+ Preconditions.checkNotNull(mInstance.mEncryptedRecoveryKeyBlob);
+ return mInstance;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mSnapshotVersion);
+ out.writeTypedList(mRecoveryMetadata);
+ out.writeByteArray(mEncryptedRecoveryKeyBlob);
+ out.writeTypedList(mEntryRecoveryData);
+ }
+
+ /**
+ * @hide
+ */
+ protected RecoveryData(Parcel in) {
+ mSnapshotVersion = in.readInt();
+ mRecoveryMetadata = in.createTypedArrayList(RecoveryMetadata.CREATOR);
+ mEncryptedRecoveryKeyBlob = in.createByteArray();
+ mEntryRecoveryData = in.createTypedArrayList(EntryRecoveryData.CREATOR);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
* limitations under the License.
*/
-package android.security.recoverablekeystore;
+package android.security.keystore;
import android.annotation.NonNull;
import android.annotation.Nullable;
*
* @hide
*/
-public class RecoverableKeyStoreLoader {
-
- public static final String PERMISSION_RECOVER_KEYSTORE = "android.permission.RECOVER_KEYSTORE";
+public class RecoveryManager {
public static final int NO_ERROR = KeyStore.NO_ERROR;
public static final int SYSTEM_ERROR = KeyStore.SYSTEM_ERROR;
private final ILockSettings mBinder;
- private RecoverableKeyStoreLoader(ILockSettings binder) {
+ private RecoveryManager(ILockSettings binder) {
mBinder = binder;
}
- /** @hide */
- public static RecoverableKeyStoreLoader getInstance() {
+ /**
+ * Gets a new instance of the class.
+ */
+ public static RecoveryManager getInstance() {
ILockSettings lockSettings =
ILockSettings.Stub.asInterface(ServiceManager.getService("lock_settings"));
- return new RecoverableKeyStoreLoader(lockSettings);
+ return new RecoveryManager(lockSettings);
}
/**
- * Exceptions returned by {@link RecoverableKeyStoreLoader}.
- *
- * @hide
+ * Exceptions returned by {@link RecoveryManager}.
*/
- public static class RecoverableKeyStoreLoaderException extends AndroidException {
+ public static class RecoveryManagerException extends AndroidException {
private int mErrorCode;
/**
- * Creates new {@link #RecoverableKeyStoreLoaderException} instance from the error code.
+ * 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 RecoverableKeyStoreLoaderException fromErrorCode(
+ public static RecoveryManagerException fromErrorCode(
int errorCode, String message) {
- return new RecoverableKeyStoreLoaderException(errorCode, message);
+ return new RecoveryManagerException(errorCode, message);
}
/**
- * Creates new {@link #RecoverableKeyStoreLoaderException} from {@link
+ * Creates new {@link #RecoveryManagerException} from {@link
* ServiceSpecificException}.
*
* @param e exception thrown on service side.
* @hide
*/
- static RecoverableKeyStoreLoaderException fromServiceSpecificException(
- ServiceSpecificException e) throws RecoverableKeyStoreLoaderException {
- throw RecoverableKeyStoreLoaderException.fromErrorCode(e.errorCode, e.getMessage());
+ static RecoveryManagerException fromServiceSpecificException(
+ ServiceSpecificException e) throws RecoveryManagerException {
+ throw RecoveryManagerException.fromErrorCode(e.errorCode, e.getMessage());
}
- private RecoverableKeyStoreLoaderException(int errorCode, String message) {
+ private RecoveryManagerException(int errorCode, String message) {
super(message);
mErrorCode = errorCode;
}
}
/**
- * Initializes key recovery service for the calling application. RecoverableKeyStoreLoader
+ * Initializes key recovery service for the calling application. RecoveryManager
* randomly chooses one of the keys from the list and keeps it to use for future key export
* operations. Collection of all keys in the list must be signed by the provided {@code
* rootCertificateAlias}, which must also be present in the list of root certificates
- * preinstalled on the device. The random selection allows RecoverableKeyStoreLoader to select
+ * preinstalled on the device. The random selection allows RecoveryManager to select
* which of a set of remote recovery service devices will be used.
*
- * <p>In addition, RecoverableKeyStoreLoader enforces a delay of three months between
+ * <p>In addition, RecoveryManager enforces a delay of three months between
* consecutive initialization attempts, to limit the ability of an attacker to often switch
* remote recovery devices and significantly increase number of recovery attempts.
*
* @param rootCertificateAlias alias of a root certificate preinstalled on the device
* @param signedPublicKeyList binary blob a list of X509 certificates and signature
- * @throws RecoverableKeyStoreLoaderException if signature is invalid, or key rotation was rate
+ * @throws RecoveryManagerException if signature is invalid, or key rotation was rate
* limited.
* @hide
*/
public void initRecoveryService(
@NonNull String rootCertificateAlias, @NonNull byte[] signedPublicKeyList)
- throws RecoverableKeyStoreLoaderException {
+ throws RecoveryManagerException {
try {
mBinder.initRecoveryService(rootCertificateAlias, signedPublicKeyList);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
- throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ throw RecoveryManagerException.fromServiceSpecificException(e);
}
}
* @return Data necessary to recover keystore.
* @hide
*/
- public @NonNull KeyStoreRecoveryData getRecoveryData(@NonNull byte[] account)
- throws RecoverableKeyStoreLoaderException {
+ public @NonNull RecoveryData getRecoveryData(@NonNull byte[] account)
+ throws RecoveryManagerException {
try {
- KeyStoreRecoveryData recoveryData = mBinder.getRecoveryData(account);
+ RecoveryData recoveryData = mBinder.getRecoveryData(account);
return recoveryData;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
- throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ throw RecoveryManagerException.fromServiceSpecificException(e);
}
}
* @hide
*/
public void setSnapshotCreatedPendingIntent(@Nullable PendingIntent intent)
- throws RecoverableKeyStoreLoaderException {
+ throws RecoveryManagerException {
try {
mBinder.setSnapshotCreatedPendingIntent(intent);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
- throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ throw RecoveryManagerException.fromServiceSpecificException(e);
}
}
* version. Version zero is used, if no snapshots were created for the account.
*
* @return Map from recovery agent accounts to snapshot versions.
- * @see KeyStoreRecoveryData#getSnapshotVersion
+ * @see RecoveryData#getSnapshotVersion
* @hide
*/
public @NonNull Map<byte[], Integer> getRecoverySnapshotVersions()
- throws RecoverableKeyStoreLoaderException {
+ throws RecoveryManagerException {
try {
// IPC doesn't support generic Maps.
@SuppressWarnings("unchecked")
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
- throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ throw RecoveryManagerException.fromServiceSpecificException(e);
}
}
/**
* Server parameters used to generate new recovery key blobs. This value will be included in
- * {@code KeyStoreRecoveryData.getEncryptedRecoveryKeyBlob()}. The same value must be included
+ * {@code RecoveryData.getEncryptedRecoveryKeyBlob()}. The same value must be included
* in vaultParams {@link #startRecoverySession}
*
* @param serverParameters included in recovery key blob.
* @see #getRecoveryData
- * @throws RecoverableKeyStoreLoaderException If parameters rotation is rate limited.
+ * @throws RecoveryManagerException If parameters rotation is rate limited.
* @hide
*/
public void setServerParameters(long serverParameters)
- throws RecoverableKeyStoreLoaderException {
+ throws RecoveryManagerException {
try {
mBinder.setServerParameters(serverParameters);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
- throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ throw RecoveryManagerException.fromServiceSpecificException(e);
}
}
*/
public void setRecoveryStatus(
@NonNull String packageName, @Nullable String[] aliases, int status)
- throws NameNotFoundException, RecoverableKeyStoreLoaderException {
+ throws NameNotFoundException, RecoveryManagerException {
try {
mBinder.setRecoveryStatus(packageName, aliases, status);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
- throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ throw RecoveryManagerException.fromServiceSpecificException(e);
}
}
* @hide
*/
public Map<String, Integer> getRecoveryStatus(@Nullable String packageName)
- throws RecoverableKeyStoreLoaderException {
+ throws RecoveryManagerException {
try {
// IPC doesn't support generic Maps.
@SuppressWarnings("unchecked")
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
- throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ throw RecoveryManagerException.fromServiceSpecificException(e);
}
}
* Specifies a set of secret types used for end-to-end keystore encryption. Knowing all of them
* is necessary to recover data.
*
- * @param secretTypes {@link KeyStoreRecoveryMetadata#TYPE_LOCKSCREEN} or {@link
- * KeyStoreRecoveryMetadata#TYPE_CUSTOM_PASSWORD}
+ * @param secretTypes {@link RecoveryMetadata#TYPE_LOCKSCREEN} or {@link
+ * RecoveryMetadata#TYPE_CUSTOM_PASSWORD}
*/
public void setRecoverySecretTypes(
- @NonNull @KeyStoreRecoveryMetadata.UserSecretType int[] secretTypes)
- throws RecoverableKeyStoreLoaderException {
+ @NonNull @RecoveryMetadata.UserSecretType int[] secretTypes)
+ throws RecoveryManagerException {
try {
mBinder.setRecoverySecretTypes(secretTypes);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
- throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ throw RecoveryManagerException.fromServiceSpecificException(e);
}
}
/**
* Defines a set of secret types used for end-to-end keystore encryption. Knowing all of them is
- * necessary to generate KeyStoreRecoveryData.
+ * necessary to generate RecoveryData.
*
* @return list of recovery secret types
- * @see KeyStoreRecoveryData
+ * @see RecoveryData
*/
- public @NonNull @KeyStoreRecoveryMetadata.UserSecretType int[] getRecoverySecretTypes()
- throws RecoverableKeyStoreLoaderException {
+ public @NonNull @RecoveryMetadata.UserSecretType int[] getRecoverySecretTypes()
+ throws RecoveryManagerException {
try {
return mBinder.getRecoverySecretTypes();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
- throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ throw RecoveryManagerException.fromServiceSpecificException(e);
}
}
* called.
*
* @return list of recovery secret types
+ * @hide
*/
- public @NonNull @KeyStoreRecoveryMetadata.UserSecretType int[] getPendingRecoverySecretTypes()
- throws RecoverableKeyStoreLoaderException {
+ public @NonNull @RecoveryMetadata.UserSecretType int[] getPendingRecoverySecretTypes()
+ throws RecoveryManagerException {
try {
return mBinder.getPendingRecoverySecretTypes();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
- throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ throw RecoveryManagerException.fromServiceSpecificException(e);
}
}
/**
* Method notifies KeyStore that a user-generated secret is available. This method generates a
* symmetric session key which a trusted remote device can use to return a recovery key. Caller
- * should use {@link KeyStoreRecoveryMetadata#clearSecret} to override the secret value in
+ * should use {@link RecoveryMetadata#clearSecret} to override the secret value in
* memory.
*
* @param recoverySecret user generated secret together with parameters necessary to regenerate
* it on a new device.
+ * @hide
*/
- public void recoverySecretAvailable(@NonNull KeyStoreRecoveryMetadata recoverySecret)
- throws RecoverableKeyStoreLoaderException {
+ public void recoverySecretAvailable(@NonNull RecoveryMetadata recoverySecret)
+ throws RecoveryManagerException {
try {
mBinder.recoverySecretAvailable(recoverySecret);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
- throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ throw RecoveryManagerException.fromServiceSpecificException(e);
}
}
@NonNull byte[] verifierPublicKey,
@NonNull byte[] vaultParams,
@NonNull byte[] vaultChallenge,
- @NonNull List<KeyStoreRecoveryMetadata> secrets)
- throws RecoverableKeyStoreLoaderException {
+ @NonNull List<RecoveryMetadata> secrets)
+ throws RecoveryManagerException {
try {
byte[] recoveryClaim =
mBinder.startRecoverySession(
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
- throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ throw RecoveryManagerException.fromServiceSpecificException(e);
}
}
* @param recoveryKeyBlob Recovery blob encrypted by symmetric key generated for this session.
* @param applicationKeys Application keys. Key material can be decrypted using recoveryKeyBlob
* and session. KeyStore only uses package names from the application info in {@link
- * KeyEntryRecoveryData}. Caller is responsibility to perform certificates check.
+ * EntryRecoveryData}. Caller is responsibility to perform certificates check.
* @return Map from alias to raw key material.
*/
public Map<String, byte[]> recoverKeys(
@NonNull String sessionId,
@NonNull byte[] recoveryKeyBlob,
- @NonNull List<KeyEntryRecoveryData> applicationKeys)
- throws RecoverableKeyStoreLoaderException {
+ @NonNull List<EntryRecoveryData> applicationKeys)
+ throws RecoveryManagerException {
try {
return (Map<String, byte[]>) mBinder.recoverKeys(
sessionId, recoveryKeyBlob, applicationKeys);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
- throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ throw RecoveryManagerException.fromServiceSpecificException(e);
}
}
* raw material of the key.
*
* @param alias The key alias.
- * @throws RecoverableKeyStoreLoaderException if an error occurred generating and storing the
+ * @throws RecoveryManagerException if an error occurred generating and storing the
* key.
*/
public byte[] generateAndStoreKey(@NonNull String alias)
- throws RecoverableKeyStoreLoaderException {
+ throws RecoveryManagerException {
try {
return mBinder.generateAndStoreKey(alias);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
- throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ throw RecoveryManagerException.fromServiceSpecificException(e);
}
}
*
* @param alias The key alias.
*/
- public void removeKey(@NonNull String alias) throws RecoverableKeyStoreLoaderException {
+ public void removeKey(@NonNull String alias) throws RecoveryManagerException {
try {
mBinder.removeKey(alias);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
- throw RecoverableKeyStoreLoaderException.fromServiceSpecificException(e);
+ throw RecoveryManagerException.fromServiceSpecificException(e);
}
}
}
* limitations under the License.
*/
-package android.security.recoverablekeystore;
+package android.security.keystore;
/* @hide */
-parcelable KeyStoreRecoveryMetadata;
+parcelable RecoveryMetadata;
* limitations under the License.
*/
-package android.security.recoverablekeystore;
+package android.security.keystore;
import android.annotation.IntDef;
import android.annotation.NonNull;
*
* @hide
*/
-public final class KeyStoreRecoveryMetadata implements Parcelable {
+public final class RecoveryMetadata implements Parcelable {
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef({TYPE_LOCKSCREEN, TYPE_CUSTOM_PASSWORD})
/**
* Lockscreen secret is required to recover KeyStore.
*/
- public static final int TYPE_LOCKSCREEN = 1;
+ public static final int TYPE_LOCKSCREEN = 100;
/**
* Custom passphrase, unrelated to lock screen, is required to recover KeyStore.
*/
- public static final int TYPE_CUSTOM_PASSWORD = 2;
+ public static final int TYPE_CUSTOM_PASSWORD = 101;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
public static final int TYPE_PATTERN = 3;
@UserSecretType
- private final int mUserSecretType;
+ private Integer mUserSecretType;
@LockScreenUiFormat
- private final int mLockScreenUiFormat;
+ private Integer mLockScreenUiFormat;
/**
* Parameters of key derivation function, including algorithm, difficulty, salt.
/**
* @param secret Constructor creates a reference to the secret. Caller must use
* @link {#clearSecret} to overwrite its value in memory.
+ * @hide
*/
- public KeyStoreRecoveryMetadata(@UserSecretType int userSecretType,
+ public RecoveryMetadata(@UserSecretType int userSecretType,
@LockScreenUiFormat int lockScreenUiFormat,
- @NonNull KeyDerivationParameters keyDerivationParameters, @NonNull byte[] secret) {
+ @NonNull KeyDerivationParameters keyDerivationParameters,
+ @NonNull byte[] secret) {
mUserSecretType = userSecretType;
mLockScreenUiFormat = lockScreenUiFormat;
mKeyDerivationParameters = Preconditions.checkNotNull(keyDerivationParameters);
mSecret = Preconditions.checkNotNull(secret);
}
+ private RecoveryMetadata() {
+
+ }
+
+ /**
+ * @see TYPE_LOCKSCREEN
+ * @see TYPE_CUSTOM_PASSWORD
+ */
+ public @UserSecretType int getUserSecretType() {
+ return mUserSecretType;
+ }
+
/**
* Specifies UX shown to user during recovery.
+ * Default value is {@code TYPE_LOCKSCREEN}
*
- * @see KeyStore.TYPE_PIN
- * @see KeyStore.TYPE_PASSWORD
- * @see KeyStore.TYPE_PATTERN
+ * @see TYPE_PIN
+ * @see TYPE_PASSWORD
+ * @see TYPE_PATTERN
*/
public @LockScreenUiFormat int getLockScreenUiFormat() {
return mLockScreenUiFormat;
}
/**
- * Secret string derived from user input.
+ * Secret derived from user input.
+ * Default value is empty array
+ *
+ * @return secret or empty array
*/
public @NonNull byte[] getSecret() {
return mSecret;
}
/**
- * @see KeyStore.TYPE_LOCKSCREEN
- * @see KeyStore.TYPE_CUSTOM_PASSWORD
+ * Builder for creating {@link RecoveryMetadata}.
*/
- public @UserSecretType int getUserSecretType() {
- return mUserSecretType;
+ public static class Builder {
+ private RecoveryMetadata mInstance = new RecoveryMetadata();
+
+ /**
+ * Sets user secret type.
+ *
+ * @see TYPE_LOCKSCREEN
+ * @see TYPE_CUSTOM_PASSWORD
+ * @param userSecretType The secret type
+ * @return This builder.
+ */
+ public Builder setUserSecretType(@UserSecretType int userSecretType) {
+ mInstance.mUserSecretType = userSecretType;
+ return this;
+ }
+
+ /**
+ * Sets UI format.
+ *
+ * @see TYPE_PIN
+ * @see TYPE_PASSWORD
+ * @see TYPE_PATTERN
+ * @param lockScreenUiFormat The UI format
+ * @return This builder.
+ */
+ public Builder setLockScreenUiFormat(@LockScreenUiFormat int lockScreenUiFormat) {
+ mInstance.mLockScreenUiFormat = lockScreenUiFormat;
+ return this;
+ }
+
+ /**
+ * Sets parameters of the key derivation function.
+ *
+ * @param keyDerivationParameters Key derivation parameters
+ * @return This builder.
+ */
+ public Builder setKeyDerivationParameters(@NonNull KeyDerivationParameters
+ keyDerivationParameters) {
+ mInstance.mKeyDerivationParameters = keyDerivationParameters;
+ return this;
+ }
+
+ /**
+ * Secret derived from user input, or empty array.
+ *
+ * @param secret The secret.
+ * @return This builder.
+ */
+ public Builder setSecret(@NonNull byte[] secret) {
+ mInstance.mSecret = secret;
+ return this;
+ }
+
+
+ /**
+ * Creates a new {@link RecoveryMetadata} instance.
+ * The instance will include default values, if {@link setSecret}
+ * or {@link setUserSecretType} were not called.
+ *
+ * @return new instance
+ * @throws NullPointerException if some required fields were not set.
+ */
+ public @NonNull RecoveryMetadata build() {
+ if (mInstance.mUserSecretType == null) {
+ mInstance.mUserSecretType = TYPE_LOCKSCREEN;
+ }
+ Preconditions.checkNotNull(mInstance.mLockScreenUiFormat);
+ Preconditions.checkNotNull(mInstance.mKeyDerivationParameters);
+ if (mInstance.mSecret == null) {
+ mInstance.mSecret = new byte[]{};
+ }
+ return mInstance;
+ }
}
/**
Arrays.fill(mSecret, (byte) 0);
}
- public static final Parcelable.Creator<KeyStoreRecoveryMetadata> CREATOR =
- new Parcelable.Creator<KeyStoreRecoveryMetadata>() {
- public KeyStoreRecoveryMetadata createFromParcel(Parcel in) {
- return new KeyStoreRecoveryMetadata(in);
+ public static final Parcelable.Creator<RecoveryMetadata> CREATOR =
+ new Parcelable.Creator<RecoveryMetadata>() {
+ public RecoveryMetadata createFromParcel(Parcel in) {
+ return new RecoveryMetadata(in);
}
- public KeyStoreRecoveryMetadata[] newArray(int length) {
- return new KeyStoreRecoveryMetadata[length];
+ public RecoveryMetadata[] newArray(int length) {
+ return new RecoveryMetadata[length];
}
};
+ /**
+ * @hide
+ */
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mUserSecretType);
out.writeByteArray(mSecret);
}
- protected KeyStoreRecoveryMetadata(Parcel in) {
+ /**
+ * @hide
+ */
+ protected RecoveryMetadata(Parcel in) {
mUserSecretType = in.readInt();
mLockScreenUiFormat = in.readInt();
mKeyDerivationParameters = in.readTypedObject(KeyDerivationParameters.CREATOR);
+++ /dev/null
-/*
- * 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.recoverablekeystore;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.util.Preconditions;
-
-/**
- * Helper class with data necessary recover a single application key, given a recovery key.
- *
- * <ul>
- * <li>Alias - Keystore alias of the key.
- * <li>Encrypted key material.
- * </ul>
- *
- * Note that Application info is not included. Recovery Agent can only make its own keys
- * recoverable.
- *
- * @hide
- */
-public final class KeyEntryRecoveryData implements Parcelable {
- private final String mAlias;
- // The only supported format is AES-256 symmetric key.
- private final byte[] mEncryptedKeyMaterial;
-
- public KeyEntryRecoveryData(@NonNull String alias, @NonNull byte[] encryptedKeyMaterial) {
- mAlias = Preconditions.checkNotNull(alias);
- mEncryptedKeyMaterial = Preconditions.checkNotNull(encryptedKeyMaterial);
- }
-
- /**
- * Application-specific alias of the key.
- *
- * @see java.security.KeyStore.aliases
- */
- public @NonNull String getAlias() {
- return mAlias;
- }
-
- /** Encrypted key material encrypted by recovery key. */
- public @NonNull byte[] getEncryptedKeyMaterial() {
- return mEncryptedKeyMaterial;
- }
-
- public static final Parcelable.Creator<KeyEntryRecoveryData> CREATOR =
- new Parcelable.Creator<KeyEntryRecoveryData>() {
- public KeyEntryRecoveryData createFromParcel(Parcel in) {
- return new KeyEntryRecoveryData(in);
- }
-
- public KeyEntryRecoveryData[] newArray(int length) {
- return new KeyEntryRecoveryData[length];
- }
- };
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(mAlias);
- out.writeByteArray(mEncryptedKeyMaterial);
- }
-
- protected KeyEntryRecoveryData(Parcel in) {
- mAlias = in.readString();
- mEncryptedKeyMaterial = in.createByteArray();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-}
+++ /dev/null
-/*
- * 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.recoverablekeystore;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.List;
-
-/**
- * Helper class which returns data necessary to recover keys.
- * Contains
- *
- * <ul>
- * <li>Snapshot version.
- * <li>Recovery metadata with UI and key derivation parameters.
- * <li>List of application keys encrypted by recovery key.
- * <li>Encrypted recovery key.
- * </ul>
- *
- * @hide
- */
-public final class KeyStoreRecoveryData implements Parcelable {
- private final int mSnapshotVersion;
- private final List<KeyStoreRecoveryMetadata> mRecoveryMetadata;
- private final List<KeyEntryRecoveryData> mApplicationKeyBlobs;
- private final byte[] mEncryptedRecoveryKeyBlob;
-
- public KeyStoreRecoveryData(int snapshotVersion, @NonNull List<KeyStoreRecoveryMetadata>
- recoveryMetadata, @NonNull List<KeyEntryRecoveryData> applicationKeyBlobs,
- @NonNull byte[] encryptedRecoveryKeyBlob) {
- mSnapshotVersion = snapshotVersion;
- mRecoveryMetadata = Preconditions.checkNotNull(recoveryMetadata);
- mApplicationKeyBlobs = Preconditions.checkNotNull(applicationKeyBlobs);
- mEncryptedRecoveryKeyBlob = Preconditions.checkNotNull(encryptedRecoveryKeyBlob);
- }
-
- /**
- * Snapshot version for given account. It is incremented when user secret or list of application
- * keys changes.
- */
- public int getSnapshotVersion() {
- return mSnapshotVersion;
- }
-
- /**
- * UI and key derivation parameters. Note that combination of secrets may be used.
- */
- public @NonNull List<KeyStoreRecoveryMetadata> getRecoveryMetadata() {
- return mRecoveryMetadata;
- }
-
- /**
- * List of application keys, with key material encrypted by
- * the recovery key ({@link #getEncryptedRecoveryKeyBlob}).
- */
- public @NonNull List<KeyEntryRecoveryData> getApplicationKeyBlobs() {
- return mApplicationKeyBlobs;
- }
-
- /**
- * Recovery key blob, encrypted by user secret and recovery service public key.
- */
- public @NonNull byte[] getEncryptedRecoveryKeyBlob() {
- return mEncryptedRecoveryKeyBlob;
- }
-
- public static final Parcelable.Creator<KeyStoreRecoveryData> CREATOR =
- new Parcelable.Creator<KeyStoreRecoveryData>() {
- public KeyStoreRecoveryData createFromParcel(Parcel in) {
- return new KeyStoreRecoveryData(in);
- }
-
- public KeyStoreRecoveryData[] newArray(int length) {
- return new KeyStoreRecoveryData[length];
- }
- };
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mSnapshotVersion);
- out.writeTypedList(mRecoveryMetadata);
- out.writeByteArray(mEncryptedRecoveryKeyBlob);
- out.writeTypedList(mApplicationKeyBlobs);
- }
-
- protected KeyStoreRecoveryData(Parcel in) {
- mSnapshotVersion = in.readInt();
- mRecoveryMetadata = in.createTypedArrayList(KeyStoreRecoveryMetadata.CREATOR);
- mEncryptedRecoveryKeyBlob = in.createByteArray();
- mApplicationKeyBlobs = in.createTypedArrayList(KeyEntryRecoveryData.CREATOR);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-}
import android.app.PendingIntent;
import android.app.trust.IStrongAuthTracker;
import android.os.Bundle;
-import android.security.recoverablekeystore.KeyEntryRecoveryData;
-import android.security.recoverablekeystore.KeyStoreRecoveryData;
-import android.security.recoverablekeystore.KeyStoreRecoveryMetadata;
+import android.security.keystore.EntryRecoveryData;
+import android.security.keystore.RecoveryData;
+import android.security.keystore.RecoveryMetadata;
import com.android.internal.widget.ICheckCredentialProgressCallback;
import com.android.internal.widget.VerifyCredentialResponse;
in byte[] token, int requestedQuality, int userId);
void unlockUserWithToken(long tokenHandle, in byte[] token, int userId);
- // RecoverableKeyStoreLoader methods.
+ // Keystore RecoveryManager methods.
// {@code ServiceSpecificException} may be thrown to signal an error, which caller can
- // convert to {@code RecoverableKeyStoreLoader}.
+ // convert to {@code RecoveryManagerException}.
void initRecoveryService(in String rootCertificateAlias, in byte[] signedPublicKeyList);
- KeyStoreRecoveryData getRecoveryData(in byte[] account);
+ RecoveryData getRecoveryData(in byte[] account);
byte[] generateAndStoreKey(String alias);
void removeKey(String alias);
void setSnapshotCreatedPendingIntent(in PendingIntent intent);
void setRecoverySecretTypes(in int[] secretTypes);
int[] getRecoverySecretTypes();
int[] getPendingRecoverySecretTypes();
- void recoverySecretAvailable(in KeyStoreRecoveryMetadata recoverySecret);
+ void recoverySecretAvailable(in RecoveryMetadata recoverySecret);
byte[] startRecoverySession(in String sessionId,
in byte[] verifierPublicKey, in byte[] vaultParams, in byte[] vaultChallenge,
- in List<KeyStoreRecoveryMetadata> secrets);
+ in List<RecoveryMetadata> secrets);
Map/*<String, byte[]>*/ recoverKeys(in String sessionId, in byte[] recoveryKeyBlob,
- in List<KeyEntryRecoveryData> applicationKeys);
+ in List<EntryRecoveryData> applicationKeys);
}
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
import android.security.keystore.UserNotAuthenticatedException;
-import android.security.recoverablekeystore.KeyEntryRecoveryData;
-import android.security.recoverablekeystore.KeyStoreRecoveryData;
-import android.security.recoverablekeystore.KeyStoreRecoveryMetadata;
-import android.security.recoverablekeystore.RecoverableKeyStoreLoader.RecoverableKeyStoreLoaderException;
+import android.security.keystore.EntryRecoveryData;
+import android.security.keystore.RecoveryData;
+import android.security.keystore.RecoveryMetadata;
+import android.security.keystore.RecoveryManager.RecoveryManagerException;
import android.service.gatekeeper.GateKeeperResponse;
import android.service.gatekeeper.IGateKeeperService;
import android.text.TextUtils;
}
@Override
- public KeyStoreRecoveryData getRecoveryData(@NonNull byte[] account) throws RemoteException {
+ public RecoveryData getRecoveryData(@NonNull byte[] account) throws RemoteException {
return mRecoverableKeyStoreManager.getRecoveryData(account);
}
}
@Override
- public void setRecoverySecretTypes(@NonNull @KeyStoreRecoveryMetadata.UserSecretType
+ public void setRecoverySecretTypes(@NonNull @RecoveryMetadata.UserSecretType
int[] secretTypes) throws RemoteException {
mRecoverableKeyStoreManager.setRecoverySecretTypes(secretTypes);
}
}
@Override
- public void recoverySecretAvailable(@NonNull KeyStoreRecoveryMetadata recoverySecret)
+ public void recoverySecretAvailable(@NonNull RecoveryMetadata recoverySecret)
throws RemoteException {
mRecoverableKeyStoreManager.recoverySecretAvailable(recoverySecret);
}
@Override
public byte[] startRecoverySession(@NonNull String sessionId,
@NonNull byte[] verifierPublicKey, @NonNull byte[] vaultParams,
- @NonNull byte[] vaultChallenge, @NonNull List<KeyStoreRecoveryMetadata> secrets)
+ @NonNull byte[] vaultChallenge, @NonNull List<RecoveryMetadata> secrets)
throws RemoteException {
return mRecoverableKeyStoreManager.startRecoverySession(sessionId, verifierPublicKey,
vaultParams, vaultChallenge, secrets);
@Override
public Map<String, byte[]> recoverKeys(@NonNull String sessionId,
- @NonNull byte[] recoveryKeyBlob, @NonNull List<KeyEntryRecoveryData> applicationKeys)
+ @NonNull byte[] recoveryKeyBlob, @NonNull List<EntryRecoveryData> applicationKeys)
throws RemoteException {
return mRecoverableKeyStoreManager.recoverKeys(
sessionId, recoveryKeyBlob, applicationKeys);
package com.android.server.locksettings.recoverablekeystore;
-import static android.security.recoverablekeystore.KeyStoreRecoveryMetadata.TYPE_LOCKSCREEN;
+import static android.security.keystore.RecoveryMetadata.TYPE_LOCKSCREEN;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
-import android.security.recoverablekeystore.KeyDerivationParameters;
-import android.security.recoverablekeystore.KeyEntryRecoveryData;
-import android.security.recoverablekeystore.KeyStoreRecoveryData;
-import android.security.recoverablekeystore.KeyStoreRecoveryMetadata;
+import android.security.keystore.KeyDerivationParameters;
+import android.security.keystore.EntryRecoveryData;
+import android.security.keystore.RecoveryData;
+import android.security.keystore.RecoveryMetadata;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
return;
}
// TODO: store raw data in RecoveryServiceMetadataEntry and generate Parcelables later
- KeyStoreRecoveryMetadata metadata = new KeyStoreRecoveryMetadata(
+ // TODO: use Builder.
+ RecoveryMetadata metadata = new RecoveryMetadata(
/*userSecretType=*/ TYPE_LOCKSCREEN,
/*lockScreenUiFormat=*/ getUiFormat(mCredentialType, mCredential),
/*keyDerivationParameters=*/ KeyDerivationParameters.createSha256Parameters(salt),
/*secret=*/ new byte[0]);
- ArrayList<KeyStoreRecoveryMetadata> metadataList = new ArrayList<>();
+ ArrayList<RecoveryMetadata> metadataList = new ArrayList<>();
metadataList.add(metadata);
int snapshotVersion = incrementSnapshotVersion(recoveryAgentUid);
// If application keys are not updated, snapshot will not be created on next unlock.
mRecoverableKeyStoreDb.setShouldCreateSnapshot(mUserId, recoveryAgentUid, false);
- mRecoverySnapshotStorage.put(recoveryAgentUid, new KeyStoreRecoveryData(
+ // TODO: use Builder.
+ mRecoverySnapshotStorage.put(recoveryAgentUid, new RecoveryData(
snapshotVersion,
/*recoveryMetadata=*/ metadataList,
/*applicationKeyBlobs=*/ createApplicationKeyEntries(encryptedApplicationKeys),
*/
private boolean shoudCreateSnapshot(int recoveryAgentUid) {
int[] types = mRecoverableKeyStoreDb.getRecoverySecretTypes(mUserId, recoveryAgentUid);
- if (!ArrayUtils.contains(types, KeyStoreRecoveryMetadata.TYPE_LOCKSCREEN)) {
+ if (!ArrayUtils.contains(types, RecoveryMetadata.TYPE_LOCKSCREEN)) {
// Only lockscreen type is supported.
// We will need to pass extra argument to KeySyncTask to support custom pass phrase.
return false;
* @return The format - either pattern, pin, or password.
*/
@VisibleForTesting
- @KeyStoreRecoveryMetadata.LockScreenUiFormat static int getUiFormat(
+ @RecoveryMetadata.LockScreenUiFormat static int getUiFormat(
int credentialType, String credential) {
if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
- return KeyStoreRecoveryMetadata.TYPE_PATTERN;
+ return RecoveryMetadata.TYPE_PATTERN;
} else if (isPin(credential)) {
- return KeyStoreRecoveryMetadata.TYPE_PIN;
+ return RecoveryMetadata.TYPE_PIN;
} else {
- return KeyStoreRecoveryMetadata.TYPE_PASSWORD;
+ return RecoveryMetadata.TYPE_PASSWORD;
}
}
return keyGenerator.generateKey();
}
- private static List<KeyEntryRecoveryData> createApplicationKeyEntries(
+ private static List<EntryRecoveryData> createApplicationKeyEntries(
Map<String, byte[]> encryptedApplicationKeys) {
- ArrayList<KeyEntryRecoveryData> keyEntries = new ArrayList<>();
+ ArrayList<EntryRecoveryData> keyEntries = new ArrayList<>();
for (String alias : encryptedApplicationKeys.keySet()) {
keyEntries.add(
- new KeyEntryRecoveryData(
+ new EntryRecoveryData(
alias,
encryptedApplicationKeys.get(alias)));
}
import javax.crypto.SecretKey;
/**
- * Utility functions for the flow where the RecoverableKeyStoreLoader syncs keys with remote
- * storage.
+ * Utility functions for the flow where the RecoveryManager syncs keys with remote storage.
*
* @hide
*/
package com.android.server.locksettings.recoverablekeystore;
-import static android.security.recoverablekeystore.RecoverableKeyStoreLoader
- .ERROR_BAD_X509_CERTIFICATE;
-import static android.security.recoverablekeystore.RecoverableKeyStoreLoader.ERROR_DATABASE_ERROR;
-import static android.security.recoverablekeystore.RecoverableKeyStoreLoader
- .ERROR_DECRYPTION_FAILED;
-import static android.security.recoverablekeystore.RecoverableKeyStoreLoader.ERROR_INSECURE_USER;
-import static android.security.recoverablekeystore.RecoverableKeyStoreLoader
- .ERROR_KEYSTORE_INTERNAL_ERROR;
-import static android.security.recoverablekeystore.RecoverableKeyStoreLoader
- .ERROR_NOT_YET_SUPPORTED;
-import static android.security.recoverablekeystore.RecoverableKeyStoreLoader
- .ERROR_UNEXPECTED_MISSING_ALGORITHM;
+import static android.security.keystore.RecoveryManager.ERROR_BAD_X509_CERTIFICATE;
+import static android.security.keystore.RecoveryManager.ERROR_DATABASE_ERROR;
+import static android.security.keystore.RecoveryManager.ERROR_DECRYPTION_FAILED;
+import static android.security.keystore.RecoveryManager.ERROR_INSECURE_USER;
+import static android.security.keystore.RecoveryManager.ERROR_KEYSTORE_INTERNAL_ERROR;
+import static android.security.keystore.RecoveryManager.ERROR_NOT_YET_SUPPORTED;
+import static android.security.keystore.RecoveryManager.ERROR_UNEXPECTED_MISSING_ALGORITHM;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.Context;
+import android.Manifest;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
-import android.security.recoverablekeystore.KeyEntryRecoveryData;
-import android.security.recoverablekeystore.KeyStoreRecoveryData;
-import android.security.recoverablekeystore.KeyStoreRecoveryMetadata;
-import android.security.recoverablekeystore.RecoverableKeyStoreLoader;
+import android.security.keystore.EntryRecoveryData;
+import android.security.keystore.RecoveryData;
+import android.security.keystore.RecoveryMetadata;
+import android.security.keystore.RecoveryManager;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import javax.crypto.AEADBadTagException;
/**
- * Class with {@link RecoverableKeyStoreLoader} API implementation and internal methods to interact
+ * Class with {@link RecoveryManager} API implementation and internal methods to interact
* with {@code LockSettingsService}.
*
* @hide
* @return recovery data
* @hide
*/
- public @NonNull KeyStoreRecoveryData getRecoveryData(@NonNull byte[] account)
+ public @NonNull RecoveryData getRecoveryData(@NonNull byte[] account)
throws RemoteException {
checkRecoverKeyStorePermission();
int uid = Binder.getCallingUid();
- KeyStoreRecoveryData snapshot = mSnapshotStorage.get(uid);
+ RecoveryData snapshot = mSnapshotStorage.get(uid);
if (snapshot == null) {
- throw new ServiceSpecificException(RecoverableKeyStoreLoader.ERROR_NO_SNAPSHOT_PENDING);
+ throw new ServiceSpecificException(RecoveryManager.ERROR_NO_SNAPSHOT_PENDING);
}
return snapshot;
}
* @hide
*/
public void setRecoverySecretTypes(
- @NonNull @KeyStoreRecoveryMetadata.UserSecretType int[] secretTypes)
+ @NonNull @RecoveryMetadata.UserSecretType int[] secretTypes)
throws RemoteException {
checkRecoverKeyStorePermission();
int userId = UserHandle.getCallingUserId();
}
/**
- * Gets secret types RecoverableKeyStoreLoaders is waiting for to create new Recovery Data.
+ * Gets secret types RecoveryManagers is waiting for to create new Recovery Data.
*
* @return secret types
* @hide
}
public void recoverySecretAvailable(
- @NonNull KeyStoreRecoveryMetadata recoverySecret) throws RemoteException {
+ @NonNull RecoveryMetadata recoverySecret) throws RemoteException {
int uid = Binder.getCallingUid();
- if (recoverySecret.getLockScreenUiFormat() == KeyStoreRecoveryMetadata.TYPE_LOCKSCREEN) {
+ if (recoverySecret.getLockScreenUiFormat() == RecoveryMetadata.TYPE_LOCKSCREEN) {
throw new SecurityException(
"Caller " + uid + " is not allowed to set lock screen secret");
}
@NonNull byte[] verifierPublicKey,
@NonNull byte[] vaultParams,
@NonNull byte[] vaultChallenge,
- @NonNull List<KeyStoreRecoveryMetadata> secrets)
+ @NonNull List<RecoveryMetadata> secrets)
throws RemoteException {
checkRecoverKeyStorePermission();
int uid = Binder.getCallingUid();
// TODO: support multiple secrets
throw new ServiceSpecificException(
ERROR_NOT_YET_SUPPORTED,
- "Only a single KeyStoreRecoveryMetadata is supported");
+ "Only a single RecoveryMetadata is supported");
}
PublicKey publicKey;
public Map<String, byte[]> recoverKeys(
@NonNull String sessionId,
@NonNull byte[] encryptedRecoveryKey,
- @NonNull List<KeyEntryRecoveryData> applicationKeys)
+ @NonNull List<EntryRecoveryData> applicationKeys)
throws RemoteException {
checkRecoverKeyStorePermission();
int uid = Binder.getCallingUid();
*/
private Map<String, byte[]> recoverApplicationKeys(
@NonNull byte[] recoveryKey,
- @NonNull List<KeyEntryRecoveryData> applicationKeys) throws RemoteException {
+ @NonNull List<EntryRecoveryData> applicationKeys) throws RemoteException {
HashMap<String, byte[]> keyMaterialByAlias = new HashMap<>();
- for (KeyEntryRecoveryData applicationKey : applicationKeys) {
+ for (EntryRecoveryData applicationKey : applicationKeys) {
String alias = applicationKey.getAlias();
byte[] encryptedKeyMaterial = applicationKey.getEncryptedKeyMaterial();
private void checkRecoverKeyStorePermission() {
mContext.enforceCallingOrSelfPermission(
- RecoverableKeyStoreLoader.PERMISSION_RECOVER_KEYSTORE,
+ Manifest.permission.RECOVER_KEYSTORE,
"Caller " + Binder.getCallingUid() + " doesn't have RecoverKeyStore permission.");
}
package com.android.server.locksettings.recoverablekeystore;
import android.util.Log;
-import android.security.recoverablekeystore.RecoverableKeyStoreLoader;
+import android.security.keystore.RecoveryManager;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
/*nonce=*/ cipher.getIV(),
/*keyMaterial=*/ encryptedKeyMaterial,
/*platformKeyGenerationId=*/ wrappingKey.getGenerationId(),
- RecoverableKeyStoreLoader.RECOVERY_STATUS_SYNC_IN_PROGRESS);
+ RecoveryManager.RECOVERY_STATUS_SYNC_IN_PROGRESS);
}
/**
* @param keyMaterial The encrypted bytes of the key material.
* @param platformKeyGenerationId The generation ID of the key used to wrap this key.
*
- * @see RecoverableKeyStoreLoader.RECOVERY_STATUS_SYNC_IN_PROGRESS
+ * @see RecoveryManager.RECOVERY_STATUS_SYNC_IN_PROGRESS
* @hide
*/
public WrappedKey(byte[] nonce, byte[] keyMaterial, int platformKeyGenerationId) {
mNonce = nonce;
mKeyMaterial = keyMaterial;
mPlatformKeyGenerationId = platformKeyGenerationId;
- mRecoveryStatus = RecoverableKeyStoreLoader.RECOVERY_STATUS_SYNC_IN_PROGRESS;
+ mRecoveryStatus = RecoveryManager.RECOVERY_STATUS_SYNC_IN_PROGRESS;
}
/**
/**
* Updates the list of user secret types used for end-to-end encryption.
* If no secret types are set, recovery snapshot will not be created.
- * See {@code KeyStoreRecoveryMetadata}
+ * See {@code RecoveryMetadata}
*
* @param userId The userId of the profile the application is running under.
* @param uid The uid of the application.
static final String COLUMN_NAME_LAST_SYNCED_AT = "last_synced_at";
/**
- * Status of the key sync {@code RecoverableKeyStoreLoader#setRecoveryStatus}
+ * Status of the key sync {@code RecoveryManager#setRecoveryStatus}
*/
static final String COLUMN_NAME_RECOVERY_STATUS = "recovery_status";
}
package com.android.server.locksettings.recoverablekeystore.storage;
import android.annotation.Nullable;
-import android.security.recoverablekeystore.KeyStoreRecoveryData;
+import android.security.keystore.RecoveryData;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
*/
public class RecoverySnapshotStorage {
@GuardedBy("this")
- private final SparseArray<KeyStoreRecoveryData> mSnapshotByUid = new SparseArray<>();
+ private final SparseArray<RecoveryData> mSnapshotByUid = new SparseArray<>();
/**
* Sets the latest {@code snapshot} for the recovery agent {@code uid}.
*/
- public synchronized void put(int uid, KeyStoreRecoveryData snapshot) {
+ public synchronized void put(int uid, RecoveryData snapshot) {
mSnapshotByUid.put(uid, snapshot);
}
* Returns the latest snapshot for the recovery agent {@code uid}, or null if none exists.
*/
@Nullable
- public synchronized KeyStoreRecoveryData get(int uid) {
+ public synchronized RecoveryData get(int uid) {
return mSnapshotByUid.get(uid);
}
package com.android.server.locksettings.recoverablekeystore;
-import static android.security.recoverablekeystore.KeyStoreRecoveryMetadata.TYPE_LOCKSCREEN;
+import static android.security.keystore.RecoveryMetadata.TYPE_LOCKSCREEN;
-import static android.security.recoverablekeystore.KeyStoreRecoveryMetadata.TYPE_PASSWORD;
-import static android.security.recoverablekeystore.KeyStoreRecoveryMetadata.TYPE_PATTERN;
-import static android.security.recoverablekeystore.KeyStoreRecoveryMetadata.TYPE_PIN;
+import static android.security.keystore.RecoveryMetadata.TYPE_PASSWORD;
+import static android.security.keystore.RecoveryMetadata.TYPE_PATTERN;
+import static android.security.keystore.RecoveryMetadata.TYPE_PIN;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
import android.security.keystore.AndroidKeyStoreSecretKey;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
-import android.security.recoverablekeystore.KeyDerivationParameters;
-import android.security.recoverablekeystore.KeyEntryRecoveryData;
-import android.security.recoverablekeystore.KeyStoreRecoveryData;
+import android.security.keystore.KeyDerivationParameters;
+import android.security.keystore.EntryRecoveryData;
+import android.security.keystore.RecoveryData;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@Test
public void run_sendsEncryptedKeysIfAvailableToSync() throws Exception {
-
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
mKeySyncTask.run();
- KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+ RecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
KeyDerivationParameters keyDerivationParameters =
recoveryData.getRecoveryMetadata().get(0).getKeyDerivationParameters();
assertThat(keyDerivationParameters.getAlgorithm()).isEqualTo(
counterId,
/*maxAttempts=*/ 10,
TEST_DEVICE_ID));
- List<KeyEntryRecoveryData> applicationKeys = recoveryData.getApplicationKeyBlobs();
+ List<EntryRecoveryData> applicationKeys = recoveryData.getEntryRecoveryData();
assertThat(applicationKeys).hasSize(1);
- KeyEntryRecoveryData keyData = applicationKeys.get(0);
+ EntryRecoveryData keyData = applicationKeys.get(0);
assertEquals(TEST_APP_KEY_ALIAS, keyData.getAlias());
assertThat(keyData.getAlias()).isEqualTo(keyData.getAlias());
byte[] appKey = KeySyncUtils.decryptApplicationKey(
@Test
public void run_setsCorrectSnapshotVersion() throws Exception {
-
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
mKeySyncTask.run();
- KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+ RecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
assertThat(recoveryData.getSnapshotVersion()).isEqualTo(1); // default value;
mRecoverableKeyStoreDb.setShouldCreateSnapshot(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, true);
mKeySyncTask.run();
- KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+ RecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
assertThat(recoveryData.getRecoveryMetadata().get(0).getLockScreenUiFormat()).
isEqualTo(TYPE_PASSWORD);
}
- @Test
+ @Test
public void run_setsCorrectTypeForPin() throws Exception {
mKeySyncTask = new KeySyncTask(
mRecoverableKeyStoreDb,
mKeySyncTask.run();
- KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+ RecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
// Password with only digits is changed to pin.
assertThat(recoveryData.getRecoveryMetadata().get(0).getLockScreenUiFormat()).
mKeySyncTask.run();
- KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+ RecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
assertThat(recoveryData.getRecoveryMetadata().get(0).getLockScreenUiFormat()).
isEqualTo(TYPE_PATTERN);
@Test
public void run_sendsEncryptedKeysOnlyForAgentWhichActiveUserSecretType() throws Exception {
mRecoverableKeyStoreDb.setRecoverySecretTypes(TEST_USER_ID, TEST_RECOVERY_AGENT_UID,
- new int[] {TYPE_LOCKSCREEN, 100});
+ new int[] {TYPE_LOCKSCREEN, 1000});
// Snapshot will not be created during unlock event.
mRecoverableKeyStoreDb.setRecoverySecretTypes(TEST_USER_ID, TEST_RECOVERY_AGENT_UID2,
- new int[] {100});
+ new int[] {1000});
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
package com.android.server.locksettings.recoverablekeystore;
-import static android.security.recoverablekeystore.KeyStoreRecoveryMetadata.TYPE_LOCKSCREEN;
-import static android.security.recoverablekeystore.KeyStoreRecoveryMetadata.TYPE_PASSWORD;
+import static android.security.keystore.RecoveryMetadata.TYPE_LOCKSCREEN;
+import static android.security.keystore.RecoveryMetadata.TYPE_PASSWORD;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertArrayEquals;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.Manifest;
import android.os.Binder;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
import android.security.keystore.AndroidKeyStoreSecretKey;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
-import android.security.recoverablekeystore.KeyDerivationParameters;
-import android.security.recoverablekeystore.KeyEntryRecoveryData;
-import android.security.recoverablekeystore.KeyStoreRecoveryMetadata;
-import android.security.recoverablekeystore.RecoverableKeyStoreLoader;
-import android.support.test.InstrumentationRegistry;
+import android.security.keystore.KeyDerivationParameters;
+import android.security.keystore.EntryRecoveryData;
+import android.security.keystore.RecoveryMetadata;
+import android.security.keystore.RecoveryManager;
import android.support.test.filters.SmallTest;
+import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb;
TEST_VAULT_PARAMS,
TEST_VAULT_CHALLENGE,
ImmutableList.of(
- new KeyStoreRecoveryMetadata(
+ new RecoveryMetadata(
TYPE_LOCKSCREEN,
TYPE_PASSWORD,
KeyDerivationParameters.createSha256Parameters(TEST_SALT),
verify(mMockContext, times(1))
.enforceCallingOrSelfPermission(
- eq(RecoverableKeyStoreLoader.PERMISSION_RECOVER_KEYSTORE), any());
+ eq(Manifest.permission.RECOVER_KEYSTORE), any());
}
@Test
TEST_VAULT_PARAMS,
TEST_VAULT_CHALLENGE,
ImmutableList.of(
- new KeyStoreRecoveryMetadata(
+ new RecoveryMetadata(
TYPE_LOCKSCREEN,
TYPE_PASSWORD,
KeyDerivationParameters.createSha256Parameters(TEST_SALT),
fail("should have thrown");
} catch (ServiceSpecificException e) {
assertThat(e.getMessage()).startsWith(
- "Only a single KeyStoreRecoveryMetadata is supported");
+ "Only a single RecoveryMetadata is supported");
}
}
TEST_VAULT_PARAMS,
TEST_VAULT_CHALLENGE,
ImmutableList.of(
- new KeyStoreRecoveryMetadata(
+ new RecoveryMetadata(
TYPE_LOCKSCREEN,
TYPE_PASSWORD,
KeyDerivationParameters.createSha256Parameters(TEST_SALT),
vaultParams,
TEST_VAULT_CHALLENGE,
ImmutableList.of(
- new KeyStoreRecoveryMetadata(
+ new RecoveryMetadata(
TYPE_LOCKSCREEN,
TYPE_PASSWORD,
KeyDerivationParameters.createSha256Parameters(TEST_SALT),
TEST_SESSION_ID,
/*recoveryKeyBlob=*/ randomBytes(32),
/*applicationKeys=*/ ImmutableList.of(
- new KeyEntryRecoveryData("alias", randomBytes(32))
+ new EntryRecoveryData("alias", randomBytes(32))
));
fail("should have thrown");
} catch (ServiceSpecificException e) {
TEST_PUBLIC_KEY,
TEST_VAULT_PARAMS,
TEST_VAULT_CHALLENGE,
- ImmutableList.of(new KeyStoreRecoveryMetadata(
+ ImmutableList.of(new RecoveryMetadata(
TYPE_LOCKSCREEN,
TYPE_PASSWORD,
KeyDerivationParameters.createSha256Parameters(TEST_SALT),
TEST_PUBLIC_KEY,
TEST_VAULT_PARAMS,
TEST_VAULT_CHALLENGE,
- ImmutableList.of(new KeyStoreRecoveryMetadata(
+ ImmutableList.of(new RecoveryMetadata(
TYPE_LOCKSCREEN,
TYPE_PASSWORD,
KeyDerivationParameters.createSha256Parameters(TEST_SALT),
SecretKey recoveryKey = randomRecoveryKey();
byte[] encryptedClaimResponse = encryptClaimResponse(
keyClaimant, TEST_SECRET, TEST_VAULT_PARAMS, recoveryKey);
- KeyEntryRecoveryData badApplicationKey = new KeyEntryRecoveryData(
+ EntryRecoveryData badApplicationKey = new EntryRecoveryData(
TEST_ALIAS,
randomBytes(32));
TEST_PUBLIC_KEY,
TEST_VAULT_PARAMS,
TEST_VAULT_CHALLENGE,
- ImmutableList.of(new KeyStoreRecoveryMetadata(
+ ImmutableList.of(new RecoveryMetadata(
TYPE_LOCKSCREEN,
TYPE_PASSWORD,
KeyDerivationParameters.createSha256Parameters(TEST_SALT),
byte[] encryptedClaimResponse = encryptClaimResponse(
keyClaimant, TEST_SECRET, TEST_VAULT_PARAMS, recoveryKey);
byte[] applicationKeyBytes = randomBytes(32);
- KeyEntryRecoveryData applicationKey = new KeyEntryRecoveryData(
+ EntryRecoveryData applicationKey = new EntryRecoveryData(
TEST_ALIAS,
encryptedApplicationKey(recoveryKey, applicationKeyBytes));
import android.content.Context;
import android.content.SharedPreferences;
-import android.security.recoverablekeystore.RecoverableKeyStoreLoader;
+import android.security.keystore.RecoveryManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
Map<String, Integer> statuses = mRecoverableKeyStoreDb.getStatusForAllKeys(uid);
assertThat(statuses).hasSize(3);
- assertThat(statuses).containsEntry(alias,
- RecoverableKeyStoreLoader.RECOVERY_STATUS_SYNC_IN_PROGRESS);
+ assertThat(statuses).containsEntry(alias, RecoveryManager.RECOVERY_STATUS_SYNC_IN_PROGRESS);
assertThat(statuses).containsEntry(alias2, status);
assertThat(statuses).containsEntry(alias3, status);
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
-import android.security.recoverablekeystore.KeyStoreRecoveryData;
+import android.security.keystore.RecoveryData;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@Test
public void get_returnsSetSnapshot() {
int userId = 1000;
- KeyStoreRecoveryData recoveryData = new KeyStoreRecoveryData(
+ RecoveryData recoveryData = new RecoveryData(
/*snapshotVersion=*/ 1,
new ArrayList<>(),
new ArrayList<>(),
@Test
public void remove_removesSnapshots() {
int userId = 1000;
- KeyStoreRecoveryData recoveryData = new KeyStoreRecoveryData(
+ RecoveryData recoveryData = new RecoveryData(
/*snapshotVersion=*/ 1,
new ArrayList<>(),
new ArrayList<>(),