summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Dementyev <dementyev@google.com>2021-02-26 06:13:35 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2021-02-26 06:13:35 +0000
commitdbf8a7c1bd0f301aec8383d1c24054c6d47c32ef (patch)
tree47f2c3ee48c0b19a471eac9a40f2b8033aee370f
parent594e8def4c99b90ea6fcfbd2eb7f845ed67d3a14 (diff)
parent16491e131633466e95923d78e30a4162251d24d7 (diff)
Merge "Migrate recoverablekeystore to KeyStore V2."
-rw-r--r--core/java/android/security/keystore/recovery/RecoveryController.java37
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java17
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java6
-rw-r--r--services/core/java/com/android/server/locksettings/recoverablekeystore/KeyStoreProxyImpl.java21
-rw-r--r--services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java2
-rw-r--r--services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java5
-rw-r--r--services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java60
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java2
8 files changed, 105 insertions, 45 deletions
diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java
index cc3e57859b64..1dc7f71fbb0e 100644
--- a/core/java/android/security/keystore/recovery/RecoveryController.java
+++ b/core/java/android/security/keystore/recovery/RecoveryController.java
@@ -27,8 +27,11 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.security.KeyStore;
-import android.security.keystore.AndroidKeyStoreProvider;
+import android.security.KeyStore2;
import android.security.keystore.KeyPermanentlyInvalidatedException;
+import android.security.keystore2.AndroidKeyStoreProvider;
+import android.system.keystore2.Domain;
+import android.system.keystore2.KeyDescriptor;
import com.android.internal.widget.ILockSettings;
@@ -709,10 +712,34 @@ public class RecoveryController {
*/
@NonNull Key getKeyFromGrant(@NonNull String grantAlias)
throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
- return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(
- mKeyStore,
- grantAlias,
- KeyStore.UID_SELF);
+ if (grantAlias.startsWith(APPLICATION_KEY_GRANT_PREFIX)) {
+ return AndroidKeyStoreProvider
+ .loadAndroidKeyStoreSecretKeyFromKeystore(
+ KeyStore2.getInstance(),
+ getGrantDescriptor(grantAlias));
+ }
+ // TODO(b/171305545): remove KeyStore1 logic.
+ return android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(
+ mKeyStore,
+ grantAlias,
+ KeyStore.UID_SELF);
+
+ }
+
+ private static final String APPLICATION_KEY_GRANT_PREFIX = "recoverable_key:";
+
+ private static @Nullable KeyDescriptor getGrantDescriptor(String grantAlias) {
+ KeyDescriptor result = new KeyDescriptor();
+ result.domain = Domain.GRANT;
+ result.blob = null;
+ result.alias = null;
+ try {
+ result.nspace = Long.parseUnsignedLong(
+ grantAlias.substring(APPLICATION_KEY_GRANT_PREFIX.length()), 16);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ return result;
}
/**
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
index 35059ac929c3..d36695b9b410 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
@@ -43,6 +43,7 @@ import java.security.interfaces.RSAPublicKey;
import javax.crypto.Cipher;
import javax.crypto.Mac;
+import javax.crypto.SecretKey;
/**
* A provider focused on providing JCA interfaces for the Android KeyStore.
@@ -299,13 +300,26 @@ public class AndroidKeyStoreProvider extends Provider {
}
}
+ /** @hide **/
+ @NonNull
+ public static SecretKey loadAndroidKeyStoreSecretKeyFromKeystore(
+ @NonNull KeyStore2 keyStore, @NonNull KeyDescriptor descriptor)
+ throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
+
+ AndroidKeyStoreKey key =
+ loadAndroidKeyStoreKeyFromKeystore(keyStore, descriptor);
+ if (key instanceof SecretKey) {
+ return (SecretKey) key;
+ } else {
+ throw new UnrecoverableKeyException("No secret key found by the given alias.");
+ }
+ }
@NonNull
private static AndroidKeyStoreSecretKey makeAndroidKeyStoreSecretKeyFromKeyEntryResponse(
@NonNull KeyDescriptor descriptor,
@NonNull KeyEntryResponse response, int algorithm, int digest)
throws UnrecoverableKeyException {
-
@KeyProperties.KeyAlgorithmEnum String keyAlgorithmString;
try {
keyAlgorithmString = KeyProperties.KeyAlgorithm.fromKeymasterSecretKeyAlgorithm(
@@ -337,7 +351,6 @@ public class AndroidKeyStoreProvider extends Provider {
public static AndroidKeyStoreKey loadAndroidKeyStoreKeyFromKeystore(
@NonNull KeyStore2 keyStore, @NonNull String alias, int namespace)
throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
-
KeyDescriptor descriptor = new KeyDescriptor();
if (namespace == KeyProperties.NAMESPACE_APPLICATION) {
descriptor.nspace = KeyProperties.NAMESPACE_APPLICATION; // ignored;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index f1750cd16f1f..294d7e257b6e 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -489,8 +489,8 @@ public class LockSettingsService extends ILockSettings.Stub {
return KeyStore.getInstance();
}
- public RecoverableKeyStoreManager getRecoverableKeyStoreManager(KeyStore keyStore) {
- return RecoverableKeyStoreManager.getInstance(mContext, keyStore);
+ public RecoverableKeyStoreManager getRecoverableKeyStoreManager() {
+ return RecoverableKeyStoreManager.getInstance(mContext);
}
public IStorageManager getStorageManager() {
@@ -571,7 +571,7 @@ public class LockSettingsService extends ILockSettings.Stub {
mInjector = injector;
mContext = injector.getContext();
mKeyStore = injector.getKeyStore();
- mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager(mKeyStore);
+ mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager();
mHandler = injector.getHandler(injector.getServiceThread());
mStrongAuth = injector.getStrongAuth();
mActivityManager = injector.getActivityManager();
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeyStoreProxyImpl.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeyStoreProxyImpl.java
index 9857fb637b59..f5941361bd89 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeyStoreProxyImpl.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeyStoreProxyImpl.java
@@ -16,8 +16,6 @@
package com.android.server.locksettings.recoverablekeystore;
-import android.security.keystore2.AndroidKeyStoreProvider;
-
import java.io.IOException;
import java.security.Key;
import java.security.KeyStore;
@@ -31,22 +29,9 @@ import java.security.cert.CertificateException;
*/
public class KeyStoreProxyImpl implements KeyStoreProxy {
- private final KeyStore mKeyStore;
-
- /**
- * TODO This function redirects keystore access to the legacy keystore during a transitional
- * phase during which not all calling code has been adjusted to use Keystore 2.0.
- * This can be reverted to a constant of "AndroidKeyStore" when b/171305684 is complete.
- * The specific bug for this component is b/171305545.
- */
- static String androidKeystoreProviderName() {
- if (AndroidKeyStoreProvider.isInstalled()) {
- return "AndroidKeyStoreLegacy";
- } else {
- return "AndroidKeyStore";
- }
+ public static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore";
- }
+ private final KeyStore mKeyStore;
/**
* A new instance, delegating to {@code keyStore}.
@@ -84,7 +69,7 @@ public class KeyStoreProxyImpl implements KeyStoreProxy {
* @throws KeyStoreException if there was a problem getting or initializing the key store.
*/
public static KeyStore getAndLoadAndroidKeyStore() throws KeyStoreException {
- KeyStore keyStore = KeyStore.getInstance(androidKeystoreProviderName());
+ KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER);
try {
keyStore.load(/*param=*/ null);
} catch (CertificateException | IOException | NoSuchAlgorithmException e) {
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
index 569b7098bb6c..202dfe798616 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
@@ -484,7 +484,7 @@ public class PlatformKeyManager {
* @throws KeyStoreException if there was a problem getting or initializing the key store.
*/
private static KeyStore getAndLoadAndroidKeyStore() throws KeyStoreException {
- KeyStore keyStore = KeyStore.getInstance(KeyStoreProxyImpl.androidKeystoreProviderName());
+ KeyStore keyStore = KeyStore.getInstance(KeyStoreProxyImpl.ANDROID_KEY_STORE_PROVIDER);
try {
keyStore.load(/*param=*/ null);
} catch (CertificateException | IOException | NoSuchAlgorithmException e) {
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index 6d97ed7a69a7..b49bced4e567 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -34,7 +34,6 @@ import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
-import android.security.KeyStore;
import android.security.keystore.recovery.KeyChainProtectionParams;
import android.security.keystore.recovery.KeyChainSnapshot;
import android.security.keystore.recovery.RecoveryCertPath;
@@ -110,14 +109,14 @@ public class RecoverableKeyStoreManager {
* @hide
*/
public static synchronized RecoverableKeyStoreManager
- getInstance(Context context, KeyStore keystore) {
+ getInstance(Context context) {
if (mInstance == null) {
RecoverableKeyStoreDb db = RecoverableKeyStoreDb.newInstance(context);
PlatformKeyManager platformKeyManager;
ApplicationKeyStorage applicationKeyStorage;
try {
platformKeyManager = PlatformKeyManager.getInstance(context, db);
- applicationKeyStorage = ApplicationKeyStorage.getInstance(keystore);
+ applicationKeyStorage = ApplicationKeyStorage.getInstance();
} catch (NoSuchAlgorithmException e) {
// Impossible: all algorithms must be supported by AOSP
throw new RuntimeException(e);
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java
index 84ddbf778c70..2398f56f847c 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java
@@ -21,9 +21,13 @@ import static android.security.keystore.recovery.RecoveryController.ERROR_SERVIC
import android.annotation.Nullable;
import android.os.ServiceSpecificException;
import android.security.Credentials;
+import android.security.KeyStore;
+import android.security.KeyStore2;
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
-import android.security.KeyStore;
+import android.system.keystore2.Domain;
+import android.system.keystore2.KeyDescriptor;
+import android.system.keystore2.KeyPermission;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -47,32 +51,37 @@ public class ApplicationKeyStorage {
private static final String APPLICATION_KEY_ALIAS_PREFIX =
"com.android.server.locksettings.recoverablekeystore/application/";
+ private static final String APPLICATION_KEY_GRANT_PREFIX = "recoverable_key:";
private final KeyStoreProxy mKeyStore;
- private final KeyStore mKeystoreService;
- public static ApplicationKeyStorage getInstance(KeyStore keystoreService)
+ /**
+ * Creates a new instance.
+ */
+ public static ApplicationKeyStorage getInstance()
throws KeyStoreException {
return new ApplicationKeyStorage(
- new KeyStoreProxyImpl(KeyStoreProxyImpl.getAndLoadAndroidKeyStore()),
- keystoreService);
+ new KeyStoreProxyImpl(KeyStoreProxyImpl.getAndLoadAndroidKeyStore()));
}
@VisibleForTesting
- ApplicationKeyStorage(KeyStoreProxy keyStore, KeyStore keystoreService) {
+ ApplicationKeyStorage(KeyStoreProxy keyStore) {
mKeyStore = keyStore;
- mKeystoreService = keystoreService;
}
/**
- * Returns grant alias, valid in Applications namespace.
+ * Returns String representation of {@code KeyDescriptor} valid in application's namespace.
*/
public @Nullable String getGrantAlias(int userId, int uid, String alias) {
- // Aliases used by {@link KeyStore} are different than used by public API.
- // {@code USER_PRIVATE_KEY} prefix is used secret keys.
Log.i(TAG, String.format(Locale.US, "Get %d/%d/%s", userId, uid, alias));
- String keystoreAlias = Credentials.USER_PRIVATE_KEY + getInternalAlias(userId, uid, alias);
- return mKeystoreService.grant(keystoreAlias, uid);
+ String keystoreAlias = getInternalAlias(userId, uid, alias);
+ if (useKeyStore2()) {
+ return makeKeystoreEngineGrantString(uid, keystoreAlias);
+ } else {
+ // Aliases used by {@link KeyStore} are different than used by public API.
+ // {@code USER_PRIVATE_KEY} prefix is used secret keys.
+ return KeyStore.getInstance().grant(Credentials.USER_PRIVATE_KEY + keystoreAlias, uid);
+ }
}
public void setSymmetricKeyEntry(int userId, int uid, String alias, byte[] secretKey)
@@ -117,4 +126,31 @@ public class ApplicationKeyStorage {
private String getInternalAlias(int userId, int uid, String alias) {
return APPLICATION_KEY_ALIAS_PREFIX + userId + "/" + uid + "/" + alias;
}
+
+ private String makeKeystoreEngineGrantString(int uid, String alias) {
+ if (alias == null) {
+ return null;
+ }
+
+ KeyDescriptor key = new KeyDescriptor();
+ key.domain = Domain.APP;
+ key.nspace = KeyProperties.NAMESPACE_APPLICATION;
+ key.alias = alias;
+ key.blob = null;
+
+ int grantAccessVector = KeyPermission.USE | KeyPermission.GET_INFO | KeyPermission.DELETE;
+
+ try {
+ key = KeyStore2.getInstance().grant(key, uid, grantAccessVector);
+ } catch (android.security.KeyStoreException e) {
+ Log.e(TAG, "Failed to get grant for KeyStore key.", e);
+ throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
+ }
+ return String.format("%s%016X", APPLICATION_KEY_GRANT_PREFIX, key.nspace);
+ }
+
+ private static boolean useKeyStore2() {
+ return android.security.keystore2.AndroidKeyStoreProvider.isInstalled();
+ }
+
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index 4e1454bd0962..1db5fcc70420 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -150,7 +150,7 @@ public class LockSettingsServiceTestable extends LockSettingsService {
}
@Override
- public RecoverableKeyStoreManager getRecoverableKeyStoreManager(KeyStore keyStore) {
+ public RecoverableKeyStoreManager getRecoverableKeyStoreManager() {
return mRecoverableKeyStoreManager;
}