Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b1a00d5e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Use better names for associated classes of RecoveryManager"

parents eb7c473f 5f138701
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -17,4 +17,4 @@
package android.security.keystore;

/* @hide */
parcelable RecoveryData;
parcelable KeychainProtectionParameter;
+30 −16
Original line number Diff line number Diff line
@@ -28,12 +28,26 @@ import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;

/**
 * Helper class with data necessary to recover Keystore on a new device.
 * It defines UI shown to the user and a way to derive a cryptographic key from user output.
 * A {@link KeychainSnapshot} is protected with a key derived from the user's lock screen. This
 * class wraps all the data necessary to derive the same key on a recovering device:
 *
 * <ul>
 *     <li>UI parameters for the user's lock screen - so that if e.g., the user was using a pattern,
 *         the recovering device can display the pattern UI to the user when asking them to enter
 *         the lock screen from their previous device.
 *     <li>The algorithm used to derive a key from the user's lock screen, e.g. SHA-256 with a salt.
 * </ul>
 *
 * <p>As such, this data is sent along with the {@link KeychainSnapshot} when syncing the current
 * version of the keychain.
 *
 * <p>For now, the recoverable keychain only supports a single layer of protection, which is the
 * user's lock screen. In the future, the keychain will support multiple layers of protection
 * (e.g. an additional keychain password, along with the lock screen).
 *
 * @hide
 */
public final class RecoveryMetadata implements Parcelable {
public final class KeychainProtectionParameter implements Parcelable {
    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({TYPE_LOCKSCREEN, TYPE_CUSTOM_PASSWORD})
@@ -88,7 +102,7 @@ public final class RecoveryMetadata implements Parcelable {
     * @link {#clearSecret} to overwrite its value in memory.
     * @hide
     */
    public RecoveryMetadata(@UserSecretType int userSecretType,
    public KeychainProtectionParameter(@UserSecretType int userSecretType,
            @LockScreenUiFormat int lockScreenUiFormat,
            @NonNull KeyDerivationParams keyDerivationParams,
            @NonNull byte[] secret) {
@@ -98,7 +112,7 @@ public final class RecoveryMetadata implements Parcelable {
        mSecret = Preconditions.checkNotNull(secret);
    }

    private RecoveryMetadata() {
    private KeychainProtectionParameter() {

    }

@@ -141,10 +155,10 @@ public final class RecoveryMetadata implements Parcelable {
    }

    /**
     * Builder for creating {@link RecoveryMetadata}.
     * Builder for creating {@link KeychainProtectionParameter}.
     */
    public static class Builder {
        private RecoveryMetadata mInstance = new RecoveryMetadata();
        private KeychainProtectionParameter mInstance = new KeychainProtectionParameter();

        /**
         * Sets user secret type.
@@ -198,14 +212,14 @@ public final class RecoveryMetadata implements Parcelable {


        /**
         * Creates a new {@link RecoveryMetadata} instance.
         * Creates a new {@link KeychainProtectionParameter} 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() {
        @NonNull public KeychainProtectionParameter build() {
            if (mInstance.mUserSecretType == null) {
                mInstance.mUserSecretType = TYPE_LOCKSCREEN;
            }
@@ -235,14 +249,14 @@ public final class RecoveryMetadata implements Parcelable {
        Arrays.fill(mSecret, (byte) 0);
    }

    public static final Parcelable.Creator<RecoveryMetadata> CREATOR =
            new Parcelable.Creator<RecoveryMetadata>() {
        public RecoveryMetadata createFromParcel(Parcel in) {
            return new RecoveryMetadata(in);
    public static final Parcelable.Creator<KeychainProtectionParameter> CREATOR =
            new Parcelable.Creator<KeychainProtectionParameter>() {
        public KeychainProtectionParameter createFromParcel(Parcel in) {
            return new KeychainProtectionParameter(in);
        }

        public RecoveryMetadata[] newArray(int length) {
            return new RecoveryMetadata[length];
        public KeychainProtectionParameter[] newArray(int length) {
            return new KeychainProtectionParameter[length];
        }
    };

@@ -260,7 +274,7 @@ public final class RecoveryMetadata implements Parcelable {
    /**
     * @hide
     */
    protected RecoveryMetadata(Parcel in) {
    protected KeychainProtectionParameter(Parcel in) {
        mUserSecretType = in.readInt();
        mLockScreenUiFormat = in.readInt();
        mKeyDerivationParams = in.readTypedObject(KeyDerivationParams.CREATOR);
+1 −1
Original line number Diff line number Diff line
@@ -17,4 +17,4 @@
package android.security.keystore;

/* @hide */
parcelable RecoveryMetadata;
parcelable KeychainSnapshot;
+45 −38
Original line number Diff line number Diff line
@@ -25,42 +25,48 @@ import com.android.internal.util.Preconditions;
import java.util.List;

/**
 * Helper class which returns data necessary to recover keys.
 * Contains
 * A snapshot of a version of the keystore. Two events can trigger the generation of a new snapshot:
 *
 * <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.
 *     <li>The user's lock screen changes. (A key derived from the user's lock screen is used to
 *         protected the keychain, which is why this forces a new snapshot.)
 *     <li>A key is added to or removed from the recoverable keychain.
 * </ul>
 *
 * <p>The snapshot data is also encrypted with the remote trusted hardware's public key, so even
 * the recovery agent itself should not be able to decipher the data. The recovery agent sends an
 * instance of this to the remote trusted hardware whenever a new snapshot is generated. During a
 * recovery flow, the recovery agent retrieves a snapshot from the remote trusted hardware. It then
 * sends it to the framework, where it is decrypted using the user's lock screen from their previous
 * device.
 *
 * @hide
 */
public final class RecoveryData implements Parcelable {
public final class KeychainSnapshot implements Parcelable {
    private int mSnapshotVersion;
    private List<RecoveryMetadata> mRecoveryMetadata;
    private List<EntryRecoveryData> mEntryRecoveryData;
    private List<KeychainProtectionParameter> mKeychainProtectionParams;
    private List<WrappedApplicationKey> mEntryRecoveryData;
    private byte[] mEncryptedRecoveryKeyBlob;

    /**
     * @hide
     * Deprecated, consider using builder.
     */
    public RecoveryData(
    public KeychainSnapshot(
            int snapshotVersion,
            @NonNull List<RecoveryMetadata> recoveryMetadata,
            @NonNull List<EntryRecoveryData> entryRecoveryData,
            @NonNull List<KeychainProtectionParameter> keychainProtectionParams,
            @NonNull List<WrappedApplicationKey> wrappedApplicationKeys,
            @NonNull byte[] encryptedRecoveryKeyBlob) {
        mSnapshotVersion = snapshotVersion;
        mRecoveryMetadata =
                Preconditions.checkCollectionElementsNotNull(recoveryMetadata, "recoveryMetadata");
        mEntryRecoveryData = Preconditions.checkCollectionElementsNotNull(entryRecoveryData,
                "entryRecoveryData");
        mKeychainProtectionParams =
                Preconditions.checkCollectionElementsNotNull(keychainProtectionParams,
                        "keychainProtectionParams");
        mEntryRecoveryData = Preconditions.checkCollectionElementsNotNull(wrappedApplicationKeys,
                "wrappedApplicationKeys");
        mEncryptedRecoveryKeyBlob = Preconditions.checkNotNull(encryptedRecoveryKeyBlob);
    }

    private RecoveryData() {
    private KeychainSnapshot() {

    }

@@ -75,15 +81,15 @@ public final class RecoveryData implements Parcelable {
    /**
     * UI and key derivation parameters. Note that combination of secrets may be used.
     */
    public @NonNull List<RecoveryMetadata> getRecoveryMetadata() {
        return mRecoveryMetadata;
    public @NonNull List<KeychainProtectionParameter> getKeychainProtectionParams() {
        return mKeychainProtectionParams;
    }

    /**
     * List of application keys, with key material encrypted by
     * the recovery key ({@link #getEncryptedRecoveryKeyBlob}).
     */
    public @NonNull List<EntryRecoveryData> getEntryRecoveryData() {
    public @NonNull List<WrappedApplicationKey> getWrappedApplicationKeys() {
        return mEntryRecoveryData;
    }

@@ -94,22 +100,22 @@ public final class RecoveryData implements Parcelable {
        return mEncryptedRecoveryKeyBlob;
    }

    public static final Parcelable.Creator<RecoveryData> CREATOR =
            new Parcelable.Creator<RecoveryData>() {
        public RecoveryData createFromParcel(Parcel in) {
            return new RecoveryData(in);
    public static final Parcelable.Creator<KeychainSnapshot> CREATOR =
            new Parcelable.Creator<KeychainSnapshot>() {
        public KeychainSnapshot createFromParcel(Parcel in) {
            return new KeychainSnapshot(in);
        }

        public RecoveryData[] newArray(int length) {
            return new RecoveryData[length];
        public KeychainSnapshot[] newArray(int length) {
            return new KeychainSnapshot[length];
        }
    };

    /**
     * Builder for creating {@link RecoveryData}.
     * Builder for creating {@link KeychainSnapshot}.
     */
    public static class Builder {
        private RecoveryData mInstance = new RecoveryData();
        private KeychainSnapshot mInstance = new KeychainSnapshot();

        /**
         * Snapshot version for given account.
@@ -128,8 +134,9 @@ public final class RecoveryData implements Parcelable {
         * @param recoveryMetadata The UI and key derivation parameters
         * @return This builder.
         */
        public Builder setRecoveryMetadata(@NonNull List<RecoveryMetadata> recoveryMetadata) {
            mInstance.mRecoveryMetadata = recoveryMetadata;
        public Builder setKeychainProtectionParams(
                @NonNull List<KeychainProtectionParameter> recoveryMetadata) {
            mInstance.mKeychainProtectionParams = recoveryMetadata;
            return this;
        }

@@ -139,7 +146,7 @@ public final class RecoveryData implements Parcelable {
         * @param entryRecoveryData List of application keys
         * @return This builder.
         */
        public Builder setEntryRecoveryData(List<EntryRecoveryData> entryRecoveryData) {
        public Builder setWrappedApplicationKeys(List<WrappedApplicationKey> entryRecoveryData) {
            mInstance.mEntryRecoveryData = entryRecoveryData;
            return this;
        }
@@ -157,13 +164,13 @@ public final class RecoveryData implements Parcelable {


        /**
         * Creates a new {@link RecoveryData} instance.
         * Creates a new {@link KeychainSnapshot} instance.
         *
         * @return new instance
         * @throws NullPointerException if some required fields were not set.
         */
        public @NonNull RecoveryData build() {
            Preconditions.checkCollectionElementsNotNull(mInstance.mRecoveryMetadata,
        @NonNull public KeychainSnapshot build() {
            Preconditions.checkCollectionElementsNotNull(mInstance.mKeychainProtectionParams,
                    "recoveryMetadata");
            Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData,
                    "entryRecoveryData");
@@ -178,7 +185,7 @@ public final class RecoveryData implements Parcelable {
    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mSnapshotVersion);
        out.writeTypedList(mRecoveryMetadata);
        out.writeTypedList(mKeychainProtectionParams);
        out.writeByteArray(mEncryptedRecoveryKeyBlob);
        out.writeTypedList(mEntryRecoveryData);
    }
@@ -186,11 +193,11 @@ public final class RecoveryData implements Parcelable {
    /**
     * @hide
     */
    protected RecoveryData(Parcel in) {
    protected KeychainSnapshot(Parcel in) {
        mSnapshotVersion = in.readInt();
        mRecoveryMetadata = in.createTypedArrayList(RecoveryMetadata.CREATOR);
        mKeychainProtectionParams = in.createTypedArrayList(KeychainProtectionParameter.CREATOR);
        mEncryptedRecoveryKeyBlob = in.createByteArray();
        mEntryRecoveryData = in.createTypedArrayList(EntryRecoveryData.CREATOR);
        mEntryRecoveryData = in.createTypedArrayList(WrappedApplicationKey.CREATOR);
    }

    @Override
+18 −17
Original line number Diff line number Diff line
@@ -99,11 +99,11 @@ public class RecoveryManager {
     * @return Data necessary to recover keystore.
     * @hide
     */
    public @NonNull RecoveryData getRecoveryData(@NonNull byte[] account)
    @NonNull public KeychainSnapshot getRecoveryData(@NonNull byte[] account)
            throws RecoveryManagerException {
        try {
            RecoveryData recoveryData = mBinder.getRecoveryData(account);
            return recoveryData;
            KeychainSnapshot keychainSnapshot = mBinder.getRecoveryData(account);
            return keychainSnapshot;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } catch (ServiceSpecificException e) {
@@ -136,7 +136,7 @@ public class RecoveryManager {
     * version. Version zero is used, if no snapshots were created for the account.
     *
     * @return Map from recovery agent accounts to snapshot versions.
     * @see RecoveryData#getSnapshotVersion
     * @see KeychainSnapshot#getSnapshotVersion
     * @hide
     */
    public @NonNull Map<byte[], Integer> getRecoverySnapshotVersions()
@@ -156,7 +156,7 @@ public class RecoveryManager {

    /**
     * Server parameters used to generate new recovery key blobs. This value will be included in
     * {@code RecoveryData.getEncryptedRecoveryKeyBlob()}. The same value must be included
     * {@code KeychainSnapshot.getEncryptedRecoveryKeyBlob()}. The same value must be included
     * in vaultParams {@link #startRecoverySession}
     *
     * @param serverParams included in recovery key blob.
@@ -230,11 +230,11 @@ public class RecoveryManager {
     * 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 RecoveryMetadata#TYPE_LOCKSCREEN} or {@link
     *     RecoveryMetadata#TYPE_CUSTOM_PASSWORD}
     * @param secretTypes {@link KeychainProtectionParameter#TYPE_LOCKSCREEN} or {@link
     *     KeychainProtectionParameter#TYPE_CUSTOM_PASSWORD}
     */
    public void setRecoverySecretTypes(
            @NonNull @RecoveryMetadata.UserSecretType int[] secretTypes)
            @NonNull @KeychainProtectionParameter.UserSecretType int[] secretTypes)
            throws RecoveryManagerException {
        try {
            mBinder.setRecoverySecretTypes(secretTypes);
@@ -247,12 +247,12 @@ public class RecoveryManager {

    /**
     * Defines a set of secret types used for end-to-end keystore encryption. Knowing all of them is
     * necessary to generate RecoveryData.
     * necessary to generate KeychainSnapshot.
     *
     * @return list of recovery secret types
     * @see RecoveryData
     * @see KeychainSnapshot
     */
    public @NonNull @RecoveryMetadata.UserSecretType int[] getRecoverySecretTypes()
    @NonNull public @KeychainProtectionParameter.UserSecretType int[] getRecoverySecretTypes()
            throws RecoveryManagerException {
        try {
            return mBinder.getRecoverySecretTypes();
@@ -271,7 +271,8 @@ public class RecoveryManager {
     * @return list of recovery secret types
     * @hide
     */
    public @NonNull @RecoveryMetadata.UserSecretType int[] getPendingRecoverySecretTypes()
    @NonNull
    public @KeychainProtectionParameter.UserSecretType int[] getPendingRecoverySecretTypes()
            throws RecoveryManagerException {
        try {
            return mBinder.getPendingRecoverySecretTypes();
@@ -285,14 +286,14 @@ public class RecoveryManager {
    /**
     * 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 RecoveryMetadata#clearSecret} to override the secret value in
     * should use {@link KeychainProtectionParameter#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 RecoveryMetadata recoverySecret)
    public void recoverySecretAvailable(@NonNull KeychainProtectionParameter recoverySecret)
            throws RecoveryManagerException {
        try {
            mBinder.recoverySecretAvailable(recoverySecret);
@@ -326,7 +327,7 @@ public class RecoveryManager {
            @NonNull byte[] verifierPublicKey,
            @NonNull byte[] vaultParams,
            @NonNull byte[] vaultChallenge,
            @NonNull List<RecoveryMetadata> secrets)
            @NonNull List<KeychainProtectionParameter> secrets)
            throws RecoveryManagerException {
        try {
            byte[] recoveryClaim =
@@ -352,13 +353,13 @@ public class RecoveryManager {
     * @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
     *     EntryRecoveryData}. Caller is responsibility to perform certificates check.
     *     WrappedApplicationKey}. 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<EntryRecoveryData> applicationKeys)
            @NonNull List<WrappedApplicationKey> applicationKeys)
            throws RecoveryManagerException {
        try {
            return (Map<String, byte[]>) mBinder.recoverKeys(
Loading