Loading core/java/android/security/keystore/recovery/RecoveryController.java +75 −3 Original line number Diff line number Diff line Loading @@ -26,9 +26,13 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.security.KeyStore; import android.security.keystore.AndroidKeyStoreProvider; import com.android.internal.widget.ILockSettings; import java.security.Key; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.List; Loading Loading @@ -113,9 +117,11 @@ public class RecoveryController { private final ILockSettings mBinder; private final KeyStore mKeyStore; private RecoveryController(ILockSettings binder) { private RecoveryController(ILockSettings binder, KeyStore keystore) { mBinder = binder; mKeyStore = keystore; } /** Loading @@ -133,7 +139,7 @@ public class RecoveryController { public static RecoveryController getInstance(Context context) { ILockSettings lockSettings = ILockSettings.Stub.asInterface(ServiceManager.getService("lock_settings")); return new RecoveryController(lockSettings); return new RecoveryController(lockSettings, KeyStore.getInstance()); } /** Loading Loading @@ -430,6 +436,7 @@ public class RecoveryController { } /** * Deprecated. * Generates a AES256/GCM/NoPADDING key called {@code alias} and loads it into the recoverable * key store. Returns the raw material of the key. * Loading @@ -444,7 +451,6 @@ public class RecoveryController { public byte[] generateAndStoreKey(@NonNull String alias, byte[] account) throws InternalRecoveryServiceException, LockScreenRequiredException { try { // TODO: add account return mBinder.generateAndStoreKey(alias); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); Loading @@ -456,6 +462,72 @@ public class RecoveryController { } } /** * Generates a AES256/GCM/NoPADDING key called {@code alias} and loads it into the recoverable * key store. Returns {@link javax.crypto.SecretKey}. * * @param alias The key alias. * @param account The account associated with the key. * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery * service. * @throws LockScreenRequiredException if the user has not set a lock screen. This is required * to generate recoverable keys, as the snapshots are encrypted using a key derived from the * lock screen. * @hide */ public Key generateKey(@NonNull String alias, byte[] account) throws InternalRecoveryServiceException, LockScreenRequiredException { // TODO: update RecoverySession.recoverKeys try { String grantAlias = mBinder.generateKey(alias, account); if (grantAlias == null) { return null; } Key result = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore( mKeyStore, grantAlias, KeyStore.UID_SELF); return result; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (UnrecoverableKeyException e) { throw new InternalRecoveryServiceException("Access to newly generated key failed for"); } catch (ServiceSpecificException e) { if (e.errorCode == ERROR_INSECURE_USER) { throw new LockScreenRequiredException(e.getMessage()); } throw wrapUnexpectedServiceSpecificException(e); } } /** * Gets a key called {@code alias} from the recoverable key store. * * @param alias The key alias. * @return The key. * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery * service. * @throws UnrecoverableKeyException if key is permanently invalidated or not found. * @hide */ public @Nullable Key getKey(@NonNull String alias) throws InternalRecoveryServiceException, UnrecoverableKeyException { try { String grantAlias = mBinder.getKey(alias); if (grantAlias == null) { return null; } return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore( mKeyStore, grantAlias, KeyStore.UID_SELF); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { throw wrapUnexpectedServiceSpecificException(e); } } /** * Removes a key called {@code alias} from the recoverable key store. * Loading core/java/com/android/internal/widget/ILockSettings.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,8 @@ interface ILockSettings { void initRecoveryService(in String rootCertificateAlias, in byte[] signedPublicKeyList); KeyChainSnapshot getKeyChainSnapshot(); byte[] generateAndStoreKey(String alias); String generateKey(String alias, in byte[] account); String getKey(String alias); void removeKey(String alias); void setSnapshotCreatedPendingIntent(in PendingIntent intent); Map getRecoverySnapshotVersions(); Loading services/core/java/com/android/server/locksettings/LockSettingsService.java +13 −3 Original line number Diff line number Diff line Loading @@ -383,8 +383,8 @@ public class LockSettingsService extends ILockSettings.Stub { return KeyStore.getInstance(); } public RecoverableKeyStoreManager getRecoverableKeyStoreManager() { return RecoverableKeyStoreManager.getInstance(mContext); public RecoverableKeyStoreManager getRecoverableKeyStoreManager(KeyStore keyStore) { return RecoverableKeyStoreManager.getInstance(mContext, keyStore); } public IStorageManager getStorageManager() { Loading Loading @@ -413,7 +413,7 @@ public class LockSettingsService extends ILockSettings.Stub { mInjector = injector; mContext = injector.getContext(); mKeyStore = injector.getKeyStore(); mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager(); mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager(mKeyStore); mHandler = injector.getHandler(); mStrongAuth = injector.getStrongAuth(); mActivityManager = injector.getActivityManager(); Loading Loading @@ -2064,6 +2064,16 @@ public class LockSettingsService extends ILockSettings.Stub { return mRecoverableKeyStoreManager.generateAndStoreKey(alias); } @Override public String generateKey(@NonNull String alias, byte[] account) throws RemoteException { return mRecoverableKeyStoreManager.generateKey(alias, account); } @Override public String getKey(@NonNull String alias) throws RemoteException { return mRecoverableKeyStoreManager.getKey(alias); } private static final String[] VALID_SETTINGS = new String[] { LockPatternUtils.LOCKOUT_PERMANENT_KEY, LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE, Loading services/core/java/com/android/server/locksettings/recoverablekeystore/KeyStoreProxyImpl.java +21 −0 Original line number Diff line number Diff line Loading @@ -16,10 +16,13 @@ package com.android.server.locksettings.recoverablekeystore; import java.io.IOException; import java.security.cert.CertificateException; import java.security.Key; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; /** Loading @@ -27,6 +30,7 @@ import java.security.UnrecoverableKeyException; */ public class KeyStoreProxyImpl implements KeyStoreProxy { private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore"; private final KeyStore mKeyStore; /** Loading Loading @@ -57,4 +61,21 @@ public class KeyStoreProxyImpl implements KeyStoreProxy { public void deleteEntry(String alias) throws KeyStoreException { mKeyStore.deleteEntry(alias); } /** * Returns AndroidKeyStore-provided {@link KeyStore}, having already invoked * {@link KeyStore#load(KeyStore.LoadStoreParameter)}. * * @throws KeyStoreException if there was a problem getting or initializing the key store. */ public static KeyStore getAndLoadAndroidKeyStore() throws KeyStoreException { KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER); try { keyStore.load(/*param=*/ null); } catch (CertificateException | IOException | NoSuchAlgorithmException e) { // Should never happen. throw new KeyStoreException("Unable to load keystore.", e); } return keyStore; } } services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java +65 −5 Original line number Diff line number Diff line Loading @@ -37,21 +37,23 @@ import android.security.keystore.recovery.KeyChainProtectionParams; import android.security.keystore.recovery.KeyChainSnapshot; import android.security.keystore.recovery.RecoveryController; import android.security.keystore.recovery.WrappedApplicationKey; import android.security.KeyStore; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.HexDump; import com.android.server.locksettings.recoverablekeystore.storage.ApplicationKeyStorage; import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb; import com.android.server.locksettings.recoverablekeystore.storage.RecoverySessionStorage; import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnapshotStorage; import java.security.InvalidKeyException; import java.security.KeyStoreException; import java.security.KeyFactory; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.UnrecoverableKeyException; import java.security.spec.InvalidKeySpecException; import java.security.UnrecoverableKeyException; import java.security.spec.X509EncodedKeySpec; import java.util.Arrays; import java.util.HashMap; Loading Loading @@ -82,18 +84,23 @@ public class RecoverableKeyStoreManager { private final RecoverableKeyGenerator mRecoverableKeyGenerator; private final RecoverySnapshotStorage mSnapshotStorage; private final PlatformKeyManager mPlatformKeyManager; private final KeyStore mKeyStore; private final ApplicationKeyStorage mApplicationKeyStorage; /** * Returns a new or existing instance. * * @hide */ public static synchronized RecoverableKeyStoreManager getInstance(Context context) { public static synchronized RecoverableKeyStoreManager getInstance(Context context, KeyStore keystore) { if (mInstance == null) { RecoverableKeyStoreDb db = RecoverableKeyStoreDb.newInstance(context); PlatformKeyManager platformKeyManager; ApplicationKeyStorage applicationKeyStorage; try { platformKeyManager = PlatformKeyManager.getInstance(context, db); applicationKeyStorage = ApplicationKeyStorage.getInstance(keystore); } catch (NoSuchAlgorithmException e) { // Impossible: all algorithms must be supported by AOSP throw new RuntimeException(e); Loading @@ -103,12 +110,14 @@ public class RecoverableKeyStoreManager { mInstance = new RecoverableKeyStoreManager( context.getApplicationContext(), keystore, db, new RecoverySessionStorage(), Executors.newSingleThreadExecutor(), new RecoverySnapshotStorage(), new RecoverySnapshotListenersStorage(), platformKeyManager); platformKeyManager, applicationKeyStorage); } return mInstance; } Loading @@ -116,19 +125,23 @@ public class RecoverableKeyStoreManager { @VisibleForTesting RecoverableKeyStoreManager( Context context, KeyStore keystore, RecoverableKeyStoreDb recoverableKeyStoreDb, RecoverySessionStorage recoverySessionStorage, ExecutorService executorService, RecoverySnapshotStorage snapshotStorage, RecoverySnapshotListenersStorage listenersStorage, PlatformKeyManager platformKeyManager) { PlatformKeyManager platformKeyManager, ApplicationKeyStorage applicationKeyStorage) { mContext = context; mKeyStore = keystore; mDatabase = recoverableKeyStoreDb; mRecoverySessionStorage = recoverySessionStorage; mExecutorService = executorService; mListenersStorage = listenersStorage; mSnapshotStorage = snapshotStorage; mPlatformKeyManager = platformKeyManager; mApplicationKeyStorage = applicationKeyStorage; try { mRecoverableKeyGenerator = RecoverableKeyGenerator.newInstance(mDatabase); Loading Loading @@ -406,6 +419,7 @@ public class RecoverableKeyStoreManager { } /** * Deprecated * Generates a key named {@code alias} in the recoverable store for the calling uid. Then * returns the raw key material. * Loading Loading @@ -450,7 +464,53 @@ public class RecoverableKeyStoreManager { boolean wasRemoved = mDatabase.removeKey(uid, alias); if (wasRemoved) { mDatabase.setShouldCreateSnapshot(userId, uid, true); mApplicationKeyStorage.deleteEntry(userId, uid, alias); } } /** * Generates a key named {@code alias} in caller's namespace. * The key is stored in system service keystore namespace. * * @return grant alias, which caller can use to access the key. */ public String generateKey(@NonNull String alias, byte[] account) throws RemoteException { int uid = Binder.getCallingUid(); int userId = UserHandle.getCallingUserId(); PlatformEncryptionKey encryptionKey; try { encryptionKey = mPlatformKeyManager.getEncryptKey(userId); } catch (NoSuchAlgorithmException e) { // Impossible: all algorithms must be supported by AOSP throw new RuntimeException(e); } catch (KeyStoreException | UnrecoverableKeyException e) { throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage()); } catch (InsecureUserException e) { throw new ServiceSpecificException(ERROR_INSECURE_USER, e.getMessage()); } try { byte[] secretKey = mRecoverableKeyGenerator.generateAndStoreKey(encryptionKey, userId, uid, alias); mApplicationKeyStorage.setSymmetricKeyEntry(userId, uid, alias, secretKey); String grantAlias = mApplicationKeyStorage.getGrantAlias(userId, uid, alias); return grantAlias; } catch (KeyStoreException | InvalidKeyException | RecoverableKeyStorageException e) { throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage()); } } /** * Gets a key named {@code alias} in caller's namespace. * * @return grant alias, which caller can use to access the key. */ public String getKey(@NonNull String alias) throws RemoteException { int uid = Binder.getCallingUid(); int userId = UserHandle.getCallingUserId(); String grantAlias = mApplicationKeyStorage.getGrantAlias(userId, uid, alias); return grantAlias; } private byte[] decryptRecoveryKey( Loading Loading
core/java/android/security/keystore/recovery/RecoveryController.java +75 −3 Original line number Diff line number Diff line Loading @@ -26,9 +26,13 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.security.KeyStore; import android.security.keystore.AndroidKeyStoreProvider; import com.android.internal.widget.ILockSettings; import java.security.Key; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.List; Loading Loading @@ -113,9 +117,11 @@ public class RecoveryController { private final ILockSettings mBinder; private final KeyStore mKeyStore; private RecoveryController(ILockSettings binder) { private RecoveryController(ILockSettings binder, KeyStore keystore) { mBinder = binder; mKeyStore = keystore; } /** Loading @@ -133,7 +139,7 @@ public class RecoveryController { public static RecoveryController getInstance(Context context) { ILockSettings lockSettings = ILockSettings.Stub.asInterface(ServiceManager.getService("lock_settings")); return new RecoveryController(lockSettings); return new RecoveryController(lockSettings, KeyStore.getInstance()); } /** Loading Loading @@ -430,6 +436,7 @@ public class RecoveryController { } /** * Deprecated. * Generates a AES256/GCM/NoPADDING key called {@code alias} and loads it into the recoverable * key store. Returns the raw material of the key. * Loading @@ -444,7 +451,6 @@ public class RecoveryController { public byte[] generateAndStoreKey(@NonNull String alias, byte[] account) throws InternalRecoveryServiceException, LockScreenRequiredException { try { // TODO: add account return mBinder.generateAndStoreKey(alias); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); Loading @@ -456,6 +462,72 @@ public class RecoveryController { } } /** * Generates a AES256/GCM/NoPADDING key called {@code alias} and loads it into the recoverable * key store. Returns {@link javax.crypto.SecretKey}. * * @param alias The key alias. * @param account The account associated with the key. * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery * service. * @throws LockScreenRequiredException if the user has not set a lock screen. This is required * to generate recoverable keys, as the snapshots are encrypted using a key derived from the * lock screen. * @hide */ public Key generateKey(@NonNull String alias, byte[] account) throws InternalRecoveryServiceException, LockScreenRequiredException { // TODO: update RecoverySession.recoverKeys try { String grantAlias = mBinder.generateKey(alias, account); if (grantAlias == null) { return null; } Key result = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore( mKeyStore, grantAlias, KeyStore.UID_SELF); return result; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (UnrecoverableKeyException e) { throw new InternalRecoveryServiceException("Access to newly generated key failed for"); } catch (ServiceSpecificException e) { if (e.errorCode == ERROR_INSECURE_USER) { throw new LockScreenRequiredException(e.getMessage()); } throw wrapUnexpectedServiceSpecificException(e); } } /** * Gets a key called {@code alias} from the recoverable key store. * * @param alias The key alias. * @return The key. * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery * service. * @throws UnrecoverableKeyException if key is permanently invalidated or not found. * @hide */ public @Nullable Key getKey(@NonNull String alias) throws InternalRecoveryServiceException, UnrecoverableKeyException { try { String grantAlias = mBinder.getKey(alias); if (grantAlias == null) { return null; } return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore( mKeyStore, grantAlias, KeyStore.UID_SELF); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { throw wrapUnexpectedServiceSpecificException(e); } } /** * Removes a key called {@code alias} from the recoverable key store. * Loading
core/java/com/android/internal/widget/ILockSettings.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,8 @@ interface ILockSettings { void initRecoveryService(in String rootCertificateAlias, in byte[] signedPublicKeyList); KeyChainSnapshot getKeyChainSnapshot(); byte[] generateAndStoreKey(String alias); String generateKey(String alias, in byte[] account); String getKey(String alias); void removeKey(String alias); void setSnapshotCreatedPendingIntent(in PendingIntent intent); Map getRecoverySnapshotVersions(); Loading
services/core/java/com/android/server/locksettings/LockSettingsService.java +13 −3 Original line number Diff line number Diff line Loading @@ -383,8 +383,8 @@ public class LockSettingsService extends ILockSettings.Stub { return KeyStore.getInstance(); } public RecoverableKeyStoreManager getRecoverableKeyStoreManager() { return RecoverableKeyStoreManager.getInstance(mContext); public RecoverableKeyStoreManager getRecoverableKeyStoreManager(KeyStore keyStore) { return RecoverableKeyStoreManager.getInstance(mContext, keyStore); } public IStorageManager getStorageManager() { Loading Loading @@ -413,7 +413,7 @@ public class LockSettingsService extends ILockSettings.Stub { mInjector = injector; mContext = injector.getContext(); mKeyStore = injector.getKeyStore(); mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager(); mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager(mKeyStore); mHandler = injector.getHandler(); mStrongAuth = injector.getStrongAuth(); mActivityManager = injector.getActivityManager(); Loading Loading @@ -2064,6 +2064,16 @@ public class LockSettingsService extends ILockSettings.Stub { return mRecoverableKeyStoreManager.generateAndStoreKey(alias); } @Override public String generateKey(@NonNull String alias, byte[] account) throws RemoteException { return mRecoverableKeyStoreManager.generateKey(alias, account); } @Override public String getKey(@NonNull String alias) throws RemoteException { return mRecoverableKeyStoreManager.getKey(alias); } private static final String[] VALID_SETTINGS = new String[] { LockPatternUtils.LOCKOUT_PERMANENT_KEY, LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE, Loading
services/core/java/com/android/server/locksettings/recoverablekeystore/KeyStoreProxyImpl.java +21 −0 Original line number Diff line number Diff line Loading @@ -16,10 +16,13 @@ package com.android.server.locksettings.recoverablekeystore; import java.io.IOException; import java.security.cert.CertificateException; import java.security.Key; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; /** Loading @@ -27,6 +30,7 @@ import java.security.UnrecoverableKeyException; */ public class KeyStoreProxyImpl implements KeyStoreProxy { private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore"; private final KeyStore mKeyStore; /** Loading Loading @@ -57,4 +61,21 @@ public class KeyStoreProxyImpl implements KeyStoreProxy { public void deleteEntry(String alias) throws KeyStoreException { mKeyStore.deleteEntry(alias); } /** * Returns AndroidKeyStore-provided {@link KeyStore}, having already invoked * {@link KeyStore#load(KeyStore.LoadStoreParameter)}. * * @throws KeyStoreException if there was a problem getting or initializing the key store. */ public static KeyStore getAndLoadAndroidKeyStore() throws KeyStoreException { KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER); try { keyStore.load(/*param=*/ null); } catch (CertificateException | IOException | NoSuchAlgorithmException e) { // Should never happen. throw new KeyStoreException("Unable to load keystore.", e); } return keyStore; } }
services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java +65 −5 Original line number Diff line number Diff line Loading @@ -37,21 +37,23 @@ import android.security.keystore.recovery.KeyChainProtectionParams; import android.security.keystore.recovery.KeyChainSnapshot; import android.security.keystore.recovery.RecoveryController; import android.security.keystore.recovery.WrappedApplicationKey; import android.security.KeyStore; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.HexDump; import com.android.server.locksettings.recoverablekeystore.storage.ApplicationKeyStorage; import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb; import com.android.server.locksettings.recoverablekeystore.storage.RecoverySessionStorage; import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnapshotStorage; import java.security.InvalidKeyException; import java.security.KeyStoreException; import java.security.KeyFactory; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.UnrecoverableKeyException; import java.security.spec.InvalidKeySpecException; import java.security.UnrecoverableKeyException; import java.security.spec.X509EncodedKeySpec; import java.util.Arrays; import java.util.HashMap; Loading Loading @@ -82,18 +84,23 @@ public class RecoverableKeyStoreManager { private final RecoverableKeyGenerator mRecoverableKeyGenerator; private final RecoverySnapshotStorage mSnapshotStorage; private final PlatformKeyManager mPlatformKeyManager; private final KeyStore mKeyStore; private final ApplicationKeyStorage mApplicationKeyStorage; /** * Returns a new or existing instance. * * @hide */ public static synchronized RecoverableKeyStoreManager getInstance(Context context) { public static synchronized RecoverableKeyStoreManager getInstance(Context context, KeyStore keystore) { if (mInstance == null) { RecoverableKeyStoreDb db = RecoverableKeyStoreDb.newInstance(context); PlatformKeyManager platformKeyManager; ApplicationKeyStorage applicationKeyStorage; try { platformKeyManager = PlatformKeyManager.getInstance(context, db); applicationKeyStorage = ApplicationKeyStorage.getInstance(keystore); } catch (NoSuchAlgorithmException e) { // Impossible: all algorithms must be supported by AOSP throw new RuntimeException(e); Loading @@ -103,12 +110,14 @@ public class RecoverableKeyStoreManager { mInstance = new RecoverableKeyStoreManager( context.getApplicationContext(), keystore, db, new RecoverySessionStorage(), Executors.newSingleThreadExecutor(), new RecoverySnapshotStorage(), new RecoverySnapshotListenersStorage(), platformKeyManager); platformKeyManager, applicationKeyStorage); } return mInstance; } Loading @@ -116,19 +125,23 @@ public class RecoverableKeyStoreManager { @VisibleForTesting RecoverableKeyStoreManager( Context context, KeyStore keystore, RecoverableKeyStoreDb recoverableKeyStoreDb, RecoverySessionStorage recoverySessionStorage, ExecutorService executorService, RecoverySnapshotStorage snapshotStorage, RecoverySnapshotListenersStorage listenersStorage, PlatformKeyManager platformKeyManager) { PlatformKeyManager platformKeyManager, ApplicationKeyStorage applicationKeyStorage) { mContext = context; mKeyStore = keystore; mDatabase = recoverableKeyStoreDb; mRecoverySessionStorage = recoverySessionStorage; mExecutorService = executorService; mListenersStorage = listenersStorage; mSnapshotStorage = snapshotStorage; mPlatformKeyManager = platformKeyManager; mApplicationKeyStorage = applicationKeyStorage; try { mRecoverableKeyGenerator = RecoverableKeyGenerator.newInstance(mDatabase); Loading Loading @@ -406,6 +419,7 @@ public class RecoverableKeyStoreManager { } /** * Deprecated * Generates a key named {@code alias} in the recoverable store for the calling uid. Then * returns the raw key material. * Loading Loading @@ -450,7 +464,53 @@ public class RecoverableKeyStoreManager { boolean wasRemoved = mDatabase.removeKey(uid, alias); if (wasRemoved) { mDatabase.setShouldCreateSnapshot(userId, uid, true); mApplicationKeyStorage.deleteEntry(userId, uid, alias); } } /** * Generates a key named {@code alias} in caller's namespace. * The key is stored in system service keystore namespace. * * @return grant alias, which caller can use to access the key. */ public String generateKey(@NonNull String alias, byte[] account) throws RemoteException { int uid = Binder.getCallingUid(); int userId = UserHandle.getCallingUserId(); PlatformEncryptionKey encryptionKey; try { encryptionKey = mPlatformKeyManager.getEncryptKey(userId); } catch (NoSuchAlgorithmException e) { // Impossible: all algorithms must be supported by AOSP throw new RuntimeException(e); } catch (KeyStoreException | UnrecoverableKeyException e) { throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage()); } catch (InsecureUserException e) { throw new ServiceSpecificException(ERROR_INSECURE_USER, e.getMessage()); } try { byte[] secretKey = mRecoverableKeyGenerator.generateAndStoreKey(encryptionKey, userId, uid, alias); mApplicationKeyStorage.setSymmetricKeyEntry(userId, uid, alias, secretKey); String grantAlias = mApplicationKeyStorage.getGrantAlias(userId, uid, alias); return grantAlias; } catch (KeyStoreException | InvalidKeyException | RecoverableKeyStorageException e) { throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage()); } } /** * Gets a key named {@code alias} in caller's namespace. * * @return grant alias, which caller can use to access the key. */ public String getKey(@NonNull String alias) throws RemoteException { int uid = Binder.getCallingUid(); int userId = UserHandle.getCallingUserId(); String grantAlias = mApplicationKeyStorage.getGrantAlias(userId, uid, alias); return grantAlias; } private byte[] decryptRecoveryKey( Loading