summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Robert Berry <robertberry@google.com> 2017-12-27 10:53:58 +0000
committer Robert Berry <robertberry@google.com> 2017-12-28 11:04:42 +0000
commitaa3f4cad33c7143679d54938aae7a37749d7f035 (patch)
tree7883ffbf2a6caf98e700f652db15fb8c9728ce99
parent7b27036950574a51edd6ade7b3c8d82b950b857a (diff)
Hook up using initialized public key in KeySyncTask
Not sure if this is correct, PTAL. We won't have a specific uid when the phone is unlocked, only the userId. Should the public key be uid-specific or just userId-specific? Test: adb shell am instrument -w -e package com.android.server.locksettings.recoverablekeystore com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner Change-Id: Ic2ec442c8a283e747542fafa9d7b0462aa185532
-rw-r--r--services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java30
-rw-r--r--services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java65
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java12
4 files changed, 78 insertions, 32 deletions
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index f6f5e59ec159..6de2445e5dd7 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -69,7 +69,6 @@ public class KeySyncTask implements Runnable {
private final int mCredentialType;
private final String mCredential;
private final PlatformKeyManager.Factory mPlatformKeyManagerFactory;
- private final VaultKeySupplier mVaultKeySupplier;
private final RecoverySnapshotStorage mRecoverySnapshotStorage;
private final RecoverySnapshotListenersStorage mSnapshotListenersStorage;
@@ -89,10 +88,7 @@ public class KeySyncTask implements Runnable {
userId,
credentialType,
credential,
- () -> PlatformKeyManager.getInstance(context, recoverableKeyStoreDb, userId),
- () -> {
- throw new UnsupportedOperationException("Not implemented vault key.");
- });
+ () -> PlatformKeyManager.getInstance(context, recoverableKeyStoreDb, userId));
}
/**
@@ -114,15 +110,13 @@ public class KeySyncTask implements Runnable {
int userId,
int credentialType,
String credential,
- PlatformKeyManager.Factory platformKeyManagerFactory,
- VaultKeySupplier vaultKeySupplier) {
+ PlatformKeyManager.Factory platformKeyManagerFactory) {
mSnapshotListenersStorage = recoverySnapshotListenersStorage;
mRecoverableKeyStoreDb = recoverableKeyStoreDb;
mUserId = userId;
mCredentialType = credentialType;
mCredential = credential;
mPlatformKeyManagerFactory = platformKeyManagerFactory;
- mVaultKeySupplier = vaultKeySupplier;
mRecoverySnapshotStorage = snapshotStorage;
}
@@ -142,7 +136,6 @@ public class KeySyncTask implements Runnable {
}
int recoveryAgentUid = mRecoverableKeyStoreDb.getRecoveryAgentUid(mUserId);
-
if (recoveryAgentUid == -1) {
Log.w(TAG, "No recovery agent initialized for user " + mUserId);
return;
@@ -153,6 +146,13 @@ public class KeySyncTask implements Runnable {
return;
}
+ PublicKey publicKey = getVaultPublicKey();
+
+ if (publicKey == null) {
+ Log.w(TAG, "Not initialized for KeySync: no public key set. Cancelling task.");
+ return;
+ }
+
byte[] salt = generateSalt();
byte[] localLskfHash = hashCredentials(salt, mCredential);
@@ -197,7 +197,7 @@ public class KeySyncTask implements Runnable {
byte[] encryptedRecoveryKey;
try {
encryptedRecoveryKey = KeySyncUtils.thmEncryptRecoveryKey(
- mVaultKeySupplier.get(),
+ publicKey,
localLskfHash,
vaultParams,
recoveryKey);
@@ -227,8 +227,7 @@ public class KeySyncTask implements Runnable {
}
private PublicKey getVaultPublicKey() {
- // TODO: fill this in
- throw new UnsupportedOperationException("TODO: get vault public key.");
+ return mRecoverableKeyStoreDb.getRecoveryServicePublicKey(mUserId);
}
/**
@@ -339,11 +338,4 @@ public class KeySyncTask implements Runnable {
}
return keyEntries;
}
-
- /**
- * TODO: until this is in the database, so we can test.
- */
- public interface VaultKeySupplier {
- PublicKey get();
- }
}
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
index e6efad5fb4b1..838311e185e8 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
@@ -22,7 +22,6 @@ import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
-import android.security.recoverablekeystore.RecoverableKeyStoreLoader;
import android.text.TextUtils;
import android.util.Log;
@@ -36,10 +35,8 @@ import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
-import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.StringJoiner;
@@ -368,6 +365,7 @@ public class RecoverableKeyStoreDb {
*
* @hide
*/
+ @Nullable
public PublicKey getRecoveryServicePublicKey(int userId, int uid) {
SQLiteDatabase db = mKeyStoreDbHelper.getReadableDatabase();
@@ -409,12 +407,8 @@ public class RecoverableKeyStoreDb {
return null;
}
byte[] keyBytes = cursor.getBlob(idx);
- X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(keyBytes);
try {
- return KeyFactory.getInstance("EC").generatePublic(pkSpec);
- } catch (NoSuchAlgorithmException e) {
- // Should never happen
- throw new RuntimeException(e);
+ return decodeX509Key(keyBytes);
} catch (InvalidKeySpecException e) {
Log.wtf(TAG,
String.format(Locale.US,
@@ -507,7 +501,7 @@ public class RecoverableKeyStoreDb {
return new int[]{};
}
String[] types = csv.split(",");
- int[] result = new int[types.length];
+ int[] result = new int[types.length];
for (int i = 0; i < types.length; i++) {
try {
result[i] = Integer.parseInt(types[i]);
@@ -520,6 +514,48 @@ public class RecoverableKeyStoreDb {
}
/**
+ * Returns the first (and only?) public key for {@code userId}.
+ *
+ * @param userId The uid of the profile whose keys are to be synced.
+ * @return The public key, or null if none exists.
+ */
+ @Nullable
+ public PublicKey getRecoveryServicePublicKey(int userId) {
+ SQLiteDatabase db = mKeyStoreDbHelper.getReadableDatabase();
+
+ String[] projection = { RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY };
+ String selection =
+ RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " = ?";
+ String[] selectionArguments = { Integer.toString(userId) };
+
+ try (
+ Cursor cursor = db.query(
+ RecoveryServiceMetadataEntry.TABLE_NAME,
+ projection,
+ selection,
+ selectionArguments,
+ /*groupBy=*/ null,
+ /*having=*/ null,
+ /*orderBy=*/ null)
+ ) {
+ if (cursor.getCount() < 1) {
+ return null;
+ }
+
+ cursor.moveToFirst();
+ byte[] keyBytes = cursor.getBlob(cursor.getColumnIndexOrThrow(
+ RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY));
+
+ try {
+ return decodeX509Key(keyBytes);
+ } catch (InvalidKeySpecException e) {
+ Log.wtf(TAG, "Could not decode public key for " + userId);
+ return null;
+ }
+ }
+ }
+
+ /**
* Updates the server parameters given by the application initializing the local recovery
* components.
*
@@ -619,5 +655,14 @@ public class RecoverableKeyStoreDb {
mKeyStoreDbHelper.close();
}
- // TODO: Add method for updating the 'last synced' time.
+ @Nullable
+ private static PublicKey decodeX509Key(byte[] keyBytes) throws InvalidKeySpecException {
+ X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(keyBytes);
+ try {
+ return KeyFactory.getInstance("EC").generatePublic(publicKeySpec);
+ } catch (NoSuchAlgorithmException e) {
+ // Should never happen
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index 8c3bf5dcd58e..4edc89d0384a 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -109,8 +109,7 @@ public class KeySyncTaskTest {
TEST_USER_ID,
TEST_CREDENTIAL_TYPE,
TEST_CREDENTIAL,
- () -> mPlatformKeyManager,
- () -> mKeyPair.getPublic());
+ () -> mPlatformKeyManager);
mWrappingKey = generateAndroidKeyStoreKey();
mEncryptKey = new PlatformEncryptionKey(TEST_GENERATION_ID, mWrappingKey);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
index a5b67af11562..a8c7d5e5adba 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
@@ -328,7 +328,6 @@ public class RecoverableKeyStoreDbTest {
}
@Test
-
public void getRecoveryAgentUid_returnsUidIfSet() throws Exception {
int userId = 12;
int uid = 190992;
@@ -437,6 +436,17 @@ public class RecoverableKeyStoreDbTest {
}
@Test
+ public void getRecoveryServicePublicKey_returnsFirstKey() throws Exception {
+ int userId = 68;
+ int uid = 12904;
+ PublicKey publicKey = genRandomPublicKey();
+
+ mRecoverableKeyStoreDb.setRecoveryServicePublicKey(userId, uid, publicKey);
+
+ assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId)).isEqualTo(publicKey);
+ }
+
+ @Test
public void setServerParameters_replaceOldValue() throws Exception {
int userId = 12;
int uid = 10009;