Loading core/java/android/security/keystore/RecoveryData.aidl→core/java/android/security/keystore/KeychainProtectionParameter.aidl +1 −1 Original line number Original line Diff line number Diff line Loading @@ -17,4 +17,4 @@ package android.security.keystore; package android.security.keystore; /* @hide */ /* @hide */ parcelable RecoveryData; parcelable KeychainProtectionParameter; core/java/android/security/keystore/RecoveryMetadata.java→core/java/android/security/keystore/KeychainProtectionParameter.java +30 −16 Original line number Original line Diff line number Diff line Loading @@ -28,12 +28,26 @@ import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.Arrays; /** /** * Helper class with data necessary to recover Keystore on a new device. * A {@link KeychainSnapshot} is protected with a key derived from the user's lock screen. This * It defines UI shown to the user and a way to derive a cryptographic key from user output. * 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 * @hide */ */ public final class RecoveryMetadata implements Parcelable { public final class KeychainProtectionParameter implements Parcelable { /** @hide */ /** @hide */ @Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE) @IntDef({TYPE_LOCKSCREEN, TYPE_CUSTOM_PASSWORD}) @IntDef({TYPE_LOCKSCREEN, TYPE_CUSTOM_PASSWORD}) Loading Loading @@ -88,7 +102,7 @@ public final class RecoveryMetadata implements Parcelable { * @link {#clearSecret} to overwrite its value in memory. * @link {#clearSecret} to overwrite its value in memory. * @hide * @hide */ */ public RecoveryMetadata(@UserSecretType int userSecretType, public KeychainProtectionParameter(@UserSecretType int userSecretType, @LockScreenUiFormat int lockScreenUiFormat, @LockScreenUiFormat int lockScreenUiFormat, @NonNull KeyDerivationParams keyDerivationParams, @NonNull KeyDerivationParams keyDerivationParams, @NonNull byte[] secret) { @NonNull byte[] secret) { Loading @@ -98,7 +112,7 @@ public final class RecoveryMetadata implements Parcelable { mSecret = Preconditions.checkNotNull(secret); mSecret = Preconditions.checkNotNull(secret); } } private RecoveryMetadata() { private KeychainProtectionParameter() { } } Loading Loading @@ -141,10 +155,10 @@ public final class RecoveryMetadata implements Parcelable { } } /** /** * Builder for creating {@link RecoveryMetadata}. * Builder for creating {@link KeychainProtectionParameter}. */ */ public static class Builder { public static class Builder { private RecoveryMetadata mInstance = new RecoveryMetadata(); private KeychainProtectionParameter mInstance = new KeychainProtectionParameter(); /** /** * Sets user secret type. * Sets user secret type. Loading Loading @@ -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} * The instance will include default values, if {@link setSecret} * or {@link setUserSecretType} were not called. * or {@link setUserSecretType} were not called. * * * @return new instance * @return new instance * @throws NullPointerException if some required fields were not set. * @throws NullPointerException if some required fields were not set. */ */ public @NonNull RecoveryMetadata build() { @NonNull public KeychainProtectionParameter build() { if (mInstance.mUserSecretType == null) { if (mInstance.mUserSecretType == null) { mInstance.mUserSecretType = TYPE_LOCKSCREEN; mInstance.mUserSecretType = TYPE_LOCKSCREEN; } } Loading Loading @@ -235,14 +249,14 @@ public final class RecoveryMetadata implements Parcelable { Arrays.fill(mSecret, (byte) 0); Arrays.fill(mSecret, (byte) 0); } } public static final Parcelable.Creator<RecoveryMetadata> CREATOR = public static final Parcelable.Creator<KeychainProtectionParameter> CREATOR = new Parcelable.Creator<RecoveryMetadata>() { new Parcelable.Creator<KeychainProtectionParameter>() { public RecoveryMetadata createFromParcel(Parcel in) { public KeychainProtectionParameter createFromParcel(Parcel in) { return new RecoveryMetadata(in); return new KeychainProtectionParameter(in); } } public RecoveryMetadata[] newArray(int length) { public KeychainProtectionParameter[] newArray(int length) { return new RecoveryMetadata[length]; return new KeychainProtectionParameter[length]; } } }; }; Loading @@ -260,7 +274,7 @@ public final class RecoveryMetadata implements Parcelable { /** /** * @hide * @hide */ */ protected RecoveryMetadata(Parcel in) { protected KeychainProtectionParameter(Parcel in) { mUserSecretType = in.readInt(); mUserSecretType = in.readInt(); mLockScreenUiFormat = in.readInt(); mLockScreenUiFormat = in.readInt(); mKeyDerivationParams = in.readTypedObject(KeyDerivationParams.CREATOR); mKeyDerivationParams = in.readTypedObject(KeyDerivationParams.CREATOR); Loading core/java/android/security/keystore/RecoveryMetadata.aidl→core/java/android/security/keystore/KeychainSnapshot.aidl +1 −1 Original line number Original line Diff line number Diff line Loading @@ -17,4 +17,4 @@ package android.security.keystore; package android.security.keystore; /* @hide */ /* @hide */ parcelable RecoveryMetadata; parcelable KeychainSnapshot; core/java/android/security/keystore/RecoveryData.java→core/java/android/security/keystore/KeychainSnapshot.java +45 −38 Original line number Original line Diff line number Diff line Loading @@ -25,42 +25,48 @@ import com.android.internal.util.Preconditions; import java.util.List; import java.util.List; /** /** * Helper class which returns data necessary to recover keys. * A snapshot of a version of the keystore. Two events can trigger the generation of a new snapshot: * Contains * * * <ul> * <ul> * <li>Snapshot version. * <li>The user's lock screen changes. (A key derived from the user's lock screen is used to * <li>Recovery metadata with UI and key derivation parameters. * protected the keychain, which is why this forces a new snapshot.) * <li>List of application keys encrypted by recovery key. * <li>A key is added to or removed from the recoverable keychain. * <li>Encrypted recovery key. * </ul> * </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 * @hide */ */ public final class RecoveryData implements Parcelable { public final class KeychainSnapshot implements Parcelable { private int mSnapshotVersion; private int mSnapshotVersion; private List<RecoveryMetadata> mRecoveryMetadata; private List<KeychainProtectionParameter> mKeychainProtectionParams; private List<EntryRecoveryData> mEntryRecoveryData; private List<WrappedApplicationKey> mEntryRecoveryData; private byte[] mEncryptedRecoveryKeyBlob; private byte[] mEncryptedRecoveryKeyBlob; /** /** * @hide * @hide * Deprecated, consider using builder. * Deprecated, consider using builder. */ */ public RecoveryData( public KeychainSnapshot( int snapshotVersion, int snapshotVersion, @NonNull List<RecoveryMetadata> recoveryMetadata, @NonNull List<KeychainProtectionParameter> keychainProtectionParams, @NonNull List<EntryRecoveryData> entryRecoveryData, @NonNull List<WrappedApplicationKey> wrappedApplicationKeys, @NonNull byte[] encryptedRecoveryKeyBlob) { @NonNull byte[] encryptedRecoveryKeyBlob) { mSnapshotVersion = snapshotVersion; mSnapshotVersion = snapshotVersion; mRecoveryMetadata = mKeychainProtectionParams = Preconditions.checkCollectionElementsNotNull(recoveryMetadata, "recoveryMetadata"); Preconditions.checkCollectionElementsNotNull(keychainProtectionParams, mEntryRecoveryData = Preconditions.checkCollectionElementsNotNull(entryRecoveryData, "keychainProtectionParams"); "entryRecoveryData"); mEntryRecoveryData = Preconditions.checkCollectionElementsNotNull(wrappedApplicationKeys, "wrappedApplicationKeys"); mEncryptedRecoveryKeyBlob = Preconditions.checkNotNull(encryptedRecoveryKeyBlob); mEncryptedRecoveryKeyBlob = Preconditions.checkNotNull(encryptedRecoveryKeyBlob); } } private RecoveryData() { private KeychainSnapshot() { } } Loading @@ -75,15 +81,15 @@ public final class RecoveryData implements Parcelable { /** /** * UI and key derivation parameters. Note that combination of secrets may be used. * UI and key derivation parameters. Note that combination of secrets may be used. */ */ public @NonNull List<RecoveryMetadata> getRecoveryMetadata() { public @NonNull List<KeychainProtectionParameter> getKeychainProtectionParams() { return mRecoveryMetadata; return mKeychainProtectionParams; } } /** /** * List of application keys, with key material encrypted by * List of application keys, with key material encrypted by * the recovery key ({@link #getEncryptedRecoveryKeyBlob}). * the recovery key ({@link #getEncryptedRecoveryKeyBlob}). */ */ public @NonNull List<EntryRecoveryData> getEntryRecoveryData() { public @NonNull List<WrappedApplicationKey> getWrappedApplicationKeys() { return mEntryRecoveryData; return mEntryRecoveryData; } } Loading @@ -94,22 +100,22 @@ public final class RecoveryData implements Parcelable { return mEncryptedRecoveryKeyBlob; return mEncryptedRecoveryKeyBlob; } } public static final Parcelable.Creator<RecoveryData> CREATOR = public static final Parcelable.Creator<KeychainSnapshot> CREATOR = new Parcelable.Creator<RecoveryData>() { new Parcelable.Creator<KeychainSnapshot>() { public RecoveryData createFromParcel(Parcel in) { public KeychainSnapshot createFromParcel(Parcel in) { return new RecoveryData(in); return new KeychainSnapshot(in); } } public RecoveryData[] newArray(int length) { public KeychainSnapshot[] newArray(int length) { return new RecoveryData[length]; return new KeychainSnapshot[length]; } } }; }; /** /** * Builder for creating {@link RecoveryData}. * Builder for creating {@link KeychainSnapshot}. */ */ public static class Builder { public static class Builder { private RecoveryData mInstance = new RecoveryData(); private KeychainSnapshot mInstance = new KeychainSnapshot(); /** /** * Snapshot version for given account. * Snapshot version for given account. Loading @@ -128,8 +134,9 @@ public final class RecoveryData implements Parcelable { * @param recoveryMetadata The UI and key derivation parameters * @param recoveryMetadata The UI and key derivation parameters * @return This builder. * @return This builder. */ */ public Builder setRecoveryMetadata(@NonNull List<RecoveryMetadata> recoveryMetadata) { public Builder setKeychainProtectionParams( mInstance.mRecoveryMetadata = recoveryMetadata; @NonNull List<KeychainProtectionParameter> recoveryMetadata) { mInstance.mKeychainProtectionParams = recoveryMetadata; return this; return this; } } Loading @@ -139,7 +146,7 @@ public final class RecoveryData implements Parcelable { * @param entryRecoveryData List of application keys * @param entryRecoveryData List of application keys * @return This builder. * @return This builder. */ */ public Builder setEntryRecoveryData(List<EntryRecoveryData> entryRecoveryData) { public Builder setWrappedApplicationKeys(List<WrappedApplicationKey> entryRecoveryData) { mInstance.mEntryRecoveryData = entryRecoveryData; mInstance.mEntryRecoveryData = entryRecoveryData; return this; return this; } } Loading @@ -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 * @return new instance * @throws NullPointerException if some required fields were not set. * @throws NullPointerException if some required fields were not set. */ */ public @NonNull RecoveryData build() { @NonNull public KeychainSnapshot build() { Preconditions.checkCollectionElementsNotNull(mInstance.mRecoveryMetadata, Preconditions.checkCollectionElementsNotNull(mInstance.mKeychainProtectionParams, "recoveryMetadata"); "recoveryMetadata"); Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData, Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData, "entryRecoveryData"); "entryRecoveryData"); Loading @@ -178,7 +185,7 @@ public final class RecoveryData implements Parcelable { @Override @Override public void writeToParcel(Parcel out, int flags) { public void writeToParcel(Parcel out, int flags) { out.writeInt(mSnapshotVersion); out.writeInt(mSnapshotVersion); out.writeTypedList(mRecoveryMetadata); out.writeTypedList(mKeychainProtectionParams); out.writeByteArray(mEncryptedRecoveryKeyBlob); out.writeByteArray(mEncryptedRecoveryKeyBlob); out.writeTypedList(mEntryRecoveryData); out.writeTypedList(mEntryRecoveryData); } } Loading @@ -186,11 +193,11 @@ public final class RecoveryData implements Parcelable { /** /** * @hide * @hide */ */ protected RecoveryData(Parcel in) { protected KeychainSnapshot(Parcel in) { mSnapshotVersion = in.readInt(); mSnapshotVersion = in.readInt(); mRecoveryMetadata = in.createTypedArrayList(RecoveryMetadata.CREATOR); mKeychainProtectionParams = in.createTypedArrayList(KeychainProtectionParameter.CREATOR); mEncryptedRecoveryKeyBlob = in.createByteArray(); mEncryptedRecoveryKeyBlob = in.createByteArray(); mEntryRecoveryData = in.createTypedArrayList(EntryRecoveryData.CREATOR); mEntryRecoveryData = in.createTypedArrayList(WrappedApplicationKey.CREATOR); } } @Override @Override Loading core/java/android/security/keystore/RecoveryManager.java +18 −17 Original line number Original line Diff line number Diff line Loading @@ -99,11 +99,11 @@ public class RecoveryManager { * @return Data necessary to recover keystore. * @return Data necessary to recover keystore. * @hide * @hide */ */ public @NonNull RecoveryData getRecoveryData(@NonNull byte[] account) @NonNull public KeychainSnapshot getRecoveryData(@NonNull byte[] account) throws RecoveryManagerException { throws RecoveryManagerException { try { try { RecoveryData recoveryData = mBinder.getRecoveryData(account); KeychainSnapshot keychainSnapshot = mBinder.getRecoveryData(account); return recoveryData; return keychainSnapshot; } catch (RemoteException e) { } catch (RemoteException e) { throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { } catch (ServiceSpecificException e) { Loading Loading @@ -136,7 +136,7 @@ public class RecoveryManager { * version. Version zero is used, if no snapshots were created for the account. * version. Version zero is used, if no snapshots were created for the account. * * * @return Map from recovery agent accounts to snapshot versions. * @return Map from recovery agent accounts to snapshot versions. * @see RecoveryData#getSnapshotVersion * @see KeychainSnapshot#getSnapshotVersion * @hide * @hide */ */ public @NonNull Map<byte[], Integer> getRecoverySnapshotVersions() public @NonNull Map<byte[], Integer> getRecoverySnapshotVersions() Loading @@ -156,7 +156,7 @@ public class RecoveryManager { /** /** * Server parameters used to generate new recovery key blobs. This value will be included in * 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} * in vaultParams {@link #startRecoverySession} * * * @param serverParams included in recovery key blob. * @param serverParams included in recovery key blob. Loading Loading @@ -230,11 +230,11 @@ public class RecoveryManager { * Specifies a set of secret types used for end-to-end keystore encryption. Knowing all of them * Specifies a set of secret types used for end-to-end keystore encryption. Knowing all of them * is necessary to recover data. * is necessary to recover data. * * * @param secretTypes {@link RecoveryMetadata#TYPE_LOCKSCREEN} or {@link * @param secretTypes {@link KeychainProtectionParameter#TYPE_LOCKSCREEN} or {@link * RecoveryMetadata#TYPE_CUSTOM_PASSWORD} * KeychainProtectionParameter#TYPE_CUSTOM_PASSWORD} */ */ public void setRecoverySecretTypes( public void setRecoverySecretTypes( @NonNull @RecoveryMetadata.UserSecretType int[] secretTypes) @NonNull @KeychainProtectionParameter.UserSecretType int[] secretTypes) throws RecoveryManagerException { throws RecoveryManagerException { try { try { mBinder.setRecoverySecretTypes(secretTypes); mBinder.setRecoverySecretTypes(secretTypes); Loading @@ -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 * 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 * @return list of recovery secret types * @see RecoveryData * @see KeychainSnapshot */ */ public @NonNull @RecoveryMetadata.UserSecretType int[] getRecoverySecretTypes() @NonNull public @KeychainProtectionParameter.UserSecretType int[] getRecoverySecretTypes() throws RecoveryManagerException { throws RecoveryManagerException { try { try { return mBinder.getRecoverySecretTypes(); return mBinder.getRecoverySecretTypes(); Loading @@ -271,7 +271,8 @@ public class RecoveryManager { * @return list of recovery secret types * @return list of recovery secret types * @hide * @hide */ */ public @NonNull @RecoveryMetadata.UserSecretType int[] getPendingRecoverySecretTypes() @NonNull public @KeychainProtectionParameter.UserSecretType int[] getPendingRecoverySecretTypes() throws RecoveryManagerException { throws RecoveryManagerException { try { try { return mBinder.getPendingRecoverySecretTypes(); return mBinder.getPendingRecoverySecretTypes(); Loading @@ -285,14 +286,14 @@ public class RecoveryManager { /** /** * Method notifies KeyStore that a user-generated secret is available. This method generates a * 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 * 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. * memory. * * * @param recoverySecret user generated secret together with parameters necessary to regenerate * @param recoverySecret user generated secret together with parameters necessary to regenerate * it on a new device. * it on a new device. * @hide * @hide */ */ public void recoverySecretAvailable(@NonNull RecoveryMetadata recoverySecret) public void recoverySecretAvailable(@NonNull KeychainProtectionParameter recoverySecret) throws RecoveryManagerException { throws RecoveryManagerException { try { try { mBinder.recoverySecretAvailable(recoverySecret); mBinder.recoverySecretAvailable(recoverySecret); Loading Loading @@ -326,7 +327,7 @@ public class RecoveryManager { @NonNull byte[] verifierPublicKey, @NonNull byte[] verifierPublicKey, @NonNull byte[] vaultParams, @NonNull byte[] vaultParams, @NonNull byte[] vaultChallenge, @NonNull byte[] vaultChallenge, @NonNull List<RecoveryMetadata> secrets) @NonNull List<KeychainProtectionParameter> secrets) throws RecoveryManagerException { throws RecoveryManagerException { try { try { byte[] recoveryClaim = byte[] recoveryClaim = Loading @@ -352,13 +353,13 @@ public class RecoveryManager { * @param recoveryKeyBlob Recovery blob encrypted by symmetric key generated for this session. * @param recoveryKeyBlob Recovery blob encrypted by symmetric key generated for this session. * @param applicationKeys Application keys. Key material can be decrypted using recoveryKeyBlob * @param applicationKeys Application keys. Key material can be decrypted using recoveryKeyBlob * and session. KeyStore only uses package names from the application info in {@link * 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. * @return Map from alias to raw key material. */ */ public Map<String, byte[]> recoverKeys( public Map<String, byte[]> recoverKeys( @NonNull String sessionId, @NonNull String sessionId, @NonNull byte[] recoveryKeyBlob, @NonNull byte[] recoveryKeyBlob, @NonNull List<EntryRecoveryData> applicationKeys) @NonNull List<WrappedApplicationKey> applicationKeys) throws RecoveryManagerException { throws RecoveryManagerException { try { try { return (Map<String, byte[]>) mBinder.recoverKeys( return (Map<String, byte[]>) mBinder.recoverKeys( Loading Loading
core/java/android/security/keystore/RecoveryData.aidl→core/java/android/security/keystore/KeychainProtectionParameter.aidl +1 −1 Original line number Original line Diff line number Diff line Loading @@ -17,4 +17,4 @@ package android.security.keystore; package android.security.keystore; /* @hide */ /* @hide */ parcelable RecoveryData; parcelable KeychainProtectionParameter;
core/java/android/security/keystore/RecoveryMetadata.java→core/java/android/security/keystore/KeychainProtectionParameter.java +30 −16 Original line number Original line Diff line number Diff line Loading @@ -28,12 +28,26 @@ import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.Arrays; /** /** * Helper class with data necessary to recover Keystore on a new device. * A {@link KeychainSnapshot} is protected with a key derived from the user's lock screen. This * It defines UI shown to the user and a way to derive a cryptographic key from user output. * 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 * @hide */ */ public final class RecoveryMetadata implements Parcelable { public final class KeychainProtectionParameter implements Parcelable { /** @hide */ /** @hide */ @Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE) @IntDef({TYPE_LOCKSCREEN, TYPE_CUSTOM_PASSWORD}) @IntDef({TYPE_LOCKSCREEN, TYPE_CUSTOM_PASSWORD}) Loading Loading @@ -88,7 +102,7 @@ public final class RecoveryMetadata implements Parcelable { * @link {#clearSecret} to overwrite its value in memory. * @link {#clearSecret} to overwrite its value in memory. * @hide * @hide */ */ public RecoveryMetadata(@UserSecretType int userSecretType, public KeychainProtectionParameter(@UserSecretType int userSecretType, @LockScreenUiFormat int lockScreenUiFormat, @LockScreenUiFormat int lockScreenUiFormat, @NonNull KeyDerivationParams keyDerivationParams, @NonNull KeyDerivationParams keyDerivationParams, @NonNull byte[] secret) { @NonNull byte[] secret) { Loading @@ -98,7 +112,7 @@ public final class RecoveryMetadata implements Parcelable { mSecret = Preconditions.checkNotNull(secret); mSecret = Preconditions.checkNotNull(secret); } } private RecoveryMetadata() { private KeychainProtectionParameter() { } } Loading Loading @@ -141,10 +155,10 @@ public final class RecoveryMetadata implements Parcelable { } } /** /** * Builder for creating {@link RecoveryMetadata}. * Builder for creating {@link KeychainProtectionParameter}. */ */ public static class Builder { public static class Builder { private RecoveryMetadata mInstance = new RecoveryMetadata(); private KeychainProtectionParameter mInstance = new KeychainProtectionParameter(); /** /** * Sets user secret type. * Sets user secret type. Loading Loading @@ -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} * The instance will include default values, if {@link setSecret} * or {@link setUserSecretType} were not called. * or {@link setUserSecretType} were not called. * * * @return new instance * @return new instance * @throws NullPointerException if some required fields were not set. * @throws NullPointerException if some required fields were not set. */ */ public @NonNull RecoveryMetadata build() { @NonNull public KeychainProtectionParameter build() { if (mInstance.mUserSecretType == null) { if (mInstance.mUserSecretType == null) { mInstance.mUserSecretType = TYPE_LOCKSCREEN; mInstance.mUserSecretType = TYPE_LOCKSCREEN; } } Loading Loading @@ -235,14 +249,14 @@ public final class RecoveryMetadata implements Parcelable { Arrays.fill(mSecret, (byte) 0); Arrays.fill(mSecret, (byte) 0); } } public static final Parcelable.Creator<RecoveryMetadata> CREATOR = public static final Parcelable.Creator<KeychainProtectionParameter> CREATOR = new Parcelable.Creator<RecoveryMetadata>() { new Parcelable.Creator<KeychainProtectionParameter>() { public RecoveryMetadata createFromParcel(Parcel in) { public KeychainProtectionParameter createFromParcel(Parcel in) { return new RecoveryMetadata(in); return new KeychainProtectionParameter(in); } } public RecoveryMetadata[] newArray(int length) { public KeychainProtectionParameter[] newArray(int length) { return new RecoveryMetadata[length]; return new KeychainProtectionParameter[length]; } } }; }; Loading @@ -260,7 +274,7 @@ public final class RecoveryMetadata implements Parcelable { /** /** * @hide * @hide */ */ protected RecoveryMetadata(Parcel in) { protected KeychainProtectionParameter(Parcel in) { mUserSecretType = in.readInt(); mUserSecretType = in.readInt(); mLockScreenUiFormat = in.readInt(); mLockScreenUiFormat = in.readInt(); mKeyDerivationParams = in.readTypedObject(KeyDerivationParams.CREATOR); mKeyDerivationParams = in.readTypedObject(KeyDerivationParams.CREATOR); Loading
core/java/android/security/keystore/RecoveryMetadata.aidl→core/java/android/security/keystore/KeychainSnapshot.aidl +1 −1 Original line number Original line Diff line number Diff line Loading @@ -17,4 +17,4 @@ package android.security.keystore; package android.security.keystore; /* @hide */ /* @hide */ parcelable RecoveryMetadata; parcelable KeychainSnapshot;
core/java/android/security/keystore/RecoveryData.java→core/java/android/security/keystore/KeychainSnapshot.java +45 −38 Original line number Original line Diff line number Diff line Loading @@ -25,42 +25,48 @@ import com.android.internal.util.Preconditions; import java.util.List; import java.util.List; /** /** * Helper class which returns data necessary to recover keys. * A snapshot of a version of the keystore. Two events can trigger the generation of a new snapshot: * Contains * * * <ul> * <ul> * <li>Snapshot version. * <li>The user's lock screen changes. (A key derived from the user's lock screen is used to * <li>Recovery metadata with UI and key derivation parameters. * protected the keychain, which is why this forces a new snapshot.) * <li>List of application keys encrypted by recovery key. * <li>A key is added to or removed from the recoverable keychain. * <li>Encrypted recovery key. * </ul> * </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 * @hide */ */ public final class RecoveryData implements Parcelable { public final class KeychainSnapshot implements Parcelable { private int mSnapshotVersion; private int mSnapshotVersion; private List<RecoveryMetadata> mRecoveryMetadata; private List<KeychainProtectionParameter> mKeychainProtectionParams; private List<EntryRecoveryData> mEntryRecoveryData; private List<WrappedApplicationKey> mEntryRecoveryData; private byte[] mEncryptedRecoveryKeyBlob; private byte[] mEncryptedRecoveryKeyBlob; /** /** * @hide * @hide * Deprecated, consider using builder. * Deprecated, consider using builder. */ */ public RecoveryData( public KeychainSnapshot( int snapshotVersion, int snapshotVersion, @NonNull List<RecoveryMetadata> recoveryMetadata, @NonNull List<KeychainProtectionParameter> keychainProtectionParams, @NonNull List<EntryRecoveryData> entryRecoveryData, @NonNull List<WrappedApplicationKey> wrappedApplicationKeys, @NonNull byte[] encryptedRecoveryKeyBlob) { @NonNull byte[] encryptedRecoveryKeyBlob) { mSnapshotVersion = snapshotVersion; mSnapshotVersion = snapshotVersion; mRecoveryMetadata = mKeychainProtectionParams = Preconditions.checkCollectionElementsNotNull(recoveryMetadata, "recoveryMetadata"); Preconditions.checkCollectionElementsNotNull(keychainProtectionParams, mEntryRecoveryData = Preconditions.checkCollectionElementsNotNull(entryRecoveryData, "keychainProtectionParams"); "entryRecoveryData"); mEntryRecoveryData = Preconditions.checkCollectionElementsNotNull(wrappedApplicationKeys, "wrappedApplicationKeys"); mEncryptedRecoveryKeyBlob = Preconditions.checkNotNull(encryptedRecoveryKeyBlob); mEncryptedRecoveryKeyBlob = Preconditions.checkNotNull(encryptedRecoveryKeyBlob); } } private RecoveryData() { private KeychainSnapshot() { } } Loading @@ -75,15 +81,15 @@ public final class RecoveryData implements Parcelable { /** /** * UI and key derivation parameters. Note that combination of secrets may be used. * UI and key derivation parameters. Note that combination of secrets may be used. */ */ public @NonNull List<RecoveryMetadata> getRecoveryMetadata() { public @NonNull List<KeychainProtectionParameter> getKeychainProtectionParams() { return mRecoveryMetadata; return mKeychainProtectionParams; } } /** /** * List of application keys, with key material encrypted by * List of application keys, with key material encrypted by * the recovery key ({@link #getEncryptedRecoveryKeyBlob}). * the recovery key ({@link #getEncryptedRecoveryKeyBlob}). */ */ public @NonNull List<EntryRecoveryData> getEntryRecoveryData() { public @NonNull List<WrappedApplicationKey> getWrappedApplicationKeys() { return mEntryRecoveryData; return mEntryRecoveryData; } } Loading @@ -94,22 +100,22 @@ public final class RecoveryData implements Parcelable { return mEncryptedRecoveryKeyBlob; return mEncryptedRecoveryKeyBlob; } } public static final Parcelable.Creator<RecoveryData> CREATOR = public static final Parcelable.Creator<KeychainSnapshot> CREATOR = new Parcelable.Creator<RecoveryData>() { new Parcelable.Creator<KeychainSnapshot>() { public RecoveryData createFromParcel(Parcel in) { public KeychainSnapshot createFromParcel(Parcel in) { return new RecoveryData(in); return new KeychainSnapshot(in); } } public RecoveryData[] newArray(int length) { public KeychainSnapshot[] newArray(int length) { return new RecoveryData[length]; return new KeychainSnapshot[length]; } } }; }; /** /** * Builder for creating {@link RecoveryData}. * Builder for creating {@link KeychainSnapshot}. */ */ public static class Builder { public static class Builder { private RecoveryData mInstance = new RecoveryData(); private KeychainSnapshot mInstance = new KeychainSnapshot(); /** /** * Snapshot version for given account. * Snapshot version for given account. Loading @@ -128,8 +134,9 @@ public final class RecoveryData implements Parcelable { * @param recoveryMetadata The UI and key derivation parameters * @param recoveryMetadata The UI and key derivation parameters * @return This builder. * @return This builder. */ */ public Builder setRecoveryMetadata(@NonNull List<RecoveryMetadata> recoveryMetadata) { public Builder setKeychainProtectionParams( mInstance.mRecoveryMetadata = recoveryMetadata; @NonNull List<KeychainProtectionParameter> recoveryMetadata) { mInstance.mKeychainProtectionParams = recoveryMetadata; return this; return this; } } Loading @@ -139,7 +146,7 @@ public final class RecoveryData implements Parcelable { * @param entryRecoveryData List of application keys * @param entryRecoveryData List of application keys * @return This builder. * @return This builder. */ */ public Builder setEntryRecoveryData(List<EntryRecoveryData> entryRecoveryData) { public Builder setWrappedApplicationKeys(List<WrappedApplicationKey> entryRecoveryData) { mInstance.mEntryRecoveryData = entryRecoveryData; mInstance.mEntryRecoveryData = entryRecoveryData; return this; return this; } } Loading @@ -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 * @return new instance * @throws NullPointerException if some required fields were not set. * @throws NullPointerException if some required fields were not set. */ */ public @NonNull RecoveryData build() { @NonNull public KeychainSnapshot build() { Preconditions.checkCollectionElementsNotNull(mInstance.mRecoveryMetadata, Preconditions.checkCollectionElementsNotNull(mInstance.mKeychainProtectionParams, "recoveryMetadata"); "recoveryMetadata"); Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData, Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData, "entryRecoveryData"); "entryRecoveryData"); Loading @@ -178,7 +185,7 @@ public final class RecoveryData implements Parcelable { @Override @Override public void writeToParcel(Parcel out, int flags) { public void writeToParcel(Parcel out, int flags) { out.writeInt(mSnapshotVersion); out.writeInt(mSnapshotVersion); out.writeTypedList(mRecoveryMetadata); out.writeTypedList(mKeychainProtectionParams); out.writeByteArray(mEncryptedRecoveryKeyBlob); out.writeByteArray(mEncryptedRecoveryKeyBlob); out.writeTypedList(mEntryRecoveryData); out.writeTypedList(mEntryRecoveryData); } } Loading @@ -186,11 +193,11 @@ public final class RecoveryData implements Parcelable { /** /** * @hide * @hide */ */ protected RecoveryData(Parcel in) { protected KeychainSnapshot(Parcel in) { mSnapshotVersion = in.readInt(); mSnapshotVersion = in.readInt(); mRecoveryMetadata = in.createTypedArrayList(RecoveryMetadata.CREATOR); mKeychainProtectionParams = in.createTypedArrayList(KeychainProtectionParameter.CREATOR); mEncryptedRecoveryKeyBlob = in.createByteArray(); mEncryptedRecoveryKeyBlob = in.createByteArray(); mEntryRecoveryData = in.createTypedArrayList(EntryRecoveryData.CREATOR); mEntryRecoveryData = in.createTypedArrayList(WrappedApplicationKey.CREATOR); } } @Override @Override Loading
core/java/android/security/keystore/RecoveryManager.java +18 −17 Original line number Original line Diff line number Diff line Loading @@ -99,11 +99,11 @@ public class RecoveryManager { * @return Data necessary to recover keystore. * @return Data necessary to recover keystore. * @hide * @hide */ */ public @NonNull RecoveryData getRecoveryData(@NonNull byte[] account) @NonNull public KeychainSnapshot getRecoveryData(@NonNull byte[] account) throws RecoveryManagerException { throws RecoveryManagerException { try { try { RecoveryData recoveryData = mBinder.getRecoveryData(account); KeychainSnapshot keychainSnapshot = mBinder.getRecoveryData(account); return recoveryData; return keychainSnapshot; } catch (RemoteException e) { } catch (RemoteException e) { throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { } catch (ServiceSpecificException e) { Loading Loading @@ -136,7 +136,7 @@ public class RecoveryManager { * version. Version zero is used, if no snapshots were created for the account. * version. Version zero is used, if no snapshots were created for the account. * * * @return Map from recovery agent accounts to snapshot versions. * @return Map from recovery agent accounts to snapshot versions. * @see RecoveryData#getSnapshotVersion * @see KeychainSnapshot#getSnapshotVersion * @hide * @hide */ */ public @NonNull Map<byte[], Integer> getRecoverySnapshotVersions() public @NonNull Map<byte[], Integer> getRecoverySnapshotVersions() Loading @@ -156,7 +156,7 @@ public class RecoveryManager { /** /** * Server parameters used to generate new recovery key blobs. This value will be included in * 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} * in vaultParams {@link #startRecoverySession} * * * @param serverParams included in recovery key blob. * @param serverParams included in recovery key blob. Loading Loading @@ -230,11 +230,11 @@ public class RecoveryManager { * Specifies a set of secret types used for end-to-end keystore encryption. Knowing all of them * Specifies a set of secret types used for end-to-end keystore encryption. Knowing all of them * is necessary to recover data. * is necessary to recover data. * * * @param secretTypes {@link RecoveryMetadata#TYPE_LOCKSCREEN} or {@link * @param secretTypes {@link KeychainProtectionParameter#TYPE_LOCKSCREEN} or {@link * RecoveryMetadata#TYPE_CUSTOM_PASSWORD} * KeychainProtectionParameter#TYPE_CUSTOM_PASSWORD} */ */ public void setRecoverySecretTypes( public void setRecoverySecretTypes( @NonNull @RecoveryMetadata.UserSecretType int[] secretTypes) @NonNull @KeychainProtectionParameter.UserSecretType int[] secretTypes) throws RecoveryManagerException { throws RecoveryManagerException { try { try { mBinder.setRecoverySecretTypes(secretTypes); mBinder.setRecoverySecretTypes(secretTypes); Loading @@ -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 * 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 * @return list of recovery secret types * @see RecoveryData * @see KeychainSnapshot */ */ public @NonNull @RecoveryMetadata.UserSecretType int[] getRecoverySecretTypes() @NonNull public @KeychainProtectionParameter.UserSecretType int[] getRecoverySecretTypes() throws RecoveryManagerException { throws RecoveryManagerException { try { try { return mBinder.getRecoverySecretTypes(); return mBinder.getRecoverySecretTypes(); Loading @@ -271,7 +271,8 @@ public class RecoveryManager { * @return list of recovery secret types * @return list of recovery secret types * @hide * @hide */ */ public @NonNull @RecoveryMetadata.UserSecretType int[] getPendingRecoverySecretTypes() @NonNull public @KeychainProtectionParameter.UserSecretType int[] getPendingRecoverySecretTypes() throws RecoveryManagerException { throws RecoveryManagerException { try { try { return mBinder.getPendingRecoverySecretTypes(); return mBinder.getPendingRecoverySecretTypes(); Loading @@ -285,14 +286,14 @@ public class RecoveryManager { /** /** * Method notifies KeyStore that a user-generated secret is available. This method generates a * 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 * 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. * memory. * * * @param recoverySecret user generated secret together with parameters necessary to regenerate * @param recoverySecret user generated secret together with parameters necessary to regenerate * it on a new device. * it on a new device. * @hide * @hide */ */ public void recoverySecretAvailable(@NonNull RecoveryMetadata recoverySecret) public void recoverySecretAvailable(@NonNull KeychainProtectionParameter recoverySecret) throws RecoveryManagerException { throws RecoveryManagerException { try { try { mBinder.recoverySecretAvailable(recoverySecret); mBinder.recoverySecretAvailable(recoverySecret); Loading Loading @@ -326,7 +327,7 @@ public class RecoveryManager { @NonNull byte[] verifierPublicKey, @NonNull byte[] verifierPublicKey, @NonNull byte[] vaultParams, @NonNull byte[] vaultParams, @NonNull byte[] vaultChallenge, @NonNull byte[] vaultChallenge, @NonNull List<RecoveryMetadata> secrets) @NonNull List<KeychainProtectionParameter> secrets) throws RecoveryManagerException { throws RecoveryManagerException { try { try { byte[] recoveryClaim = byte[] recoveryClaim = Loading @@ -352,13 +353,13 @@ public class RecoveryManager { * @param recoveryKeyBlob Recovery blob encrypted by symmetric key generated for this session. * @param recoveryKeyBlob Recovery blob encrypted by symmetric key generated for this session. * @param applicationKeys Application keys. Key material can be decrypted using recoveryKeyBlob * @param applicationKeys Application keys. Key material can be decrypted using recoveryKeyBlob * and session. KeyStore only uses package names from the application info in {@link * 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. * @return Map from alias to raw key material. */ */ public Map<String, byte[]> recoverKeys( public Map<String, byte[]> recoverKeys( @NonNull String sessionId, @NonNull String sessionId, @NonNull byte[] recoveryKeyBlob, @NonNull byte[] recoveryKeyBlob, @NonNull List<EntryRecoveryData> applicationKeys) @NonNull List<WrappedApplicationKey> applicationKeys) throws RecoveryManagerException { throws RecoveryManagerException { try { try { return (Map<String, byte[]>) mBinder.recoverKeys( return (Map<String, byte[]>) mBinder.recoverKeys( Loading