From 1b9c03429f8590cce7379fc765d810b5197fdcef Mon Sep 17 00:00:00 2001 From: Dmitry Dementyev Date: Wed, 24 Apr 2019 12:38:05 -0700 Subject: [PATCH] Use SQLite update instead of replace in UserMetadata table. Replace doesn't work since we use this table to store two values. Bug: 131243739 Test: atest FrameworksServicesTests:com.android.server.locksettings.recoverablekeystore Change-Id: I024f631c73ddc5316acade0e9b385cd2261cc1dc --- .../recoverablekeystore/PlatformKeyManager.java | 5 +-- .../storage/RecoverableKeyStoreDb.java | 36 +++++++++++++++------- .../storage/RecoverableKeyStoreDbTest.java | 26 ++++++++++++++++ 3 files changed, 52 insertions(+), 15 deletions(-) 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 1c187713540a..c54bfc01e031 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java @@ -400,10 +400,7 @@ public class PlatformKeyManager { * @throws IOException if there was an issue with local database update. */ private void setGenerationId(int userId, int generationId) throws IOException { - long updatedRows = mDatabase.setPlatformKeyGenerationId(userId, generationId); - if (updatedRows < 0) { - throw new IOException("Failed to set the platform key in the local DB."); - } + mDatabase.setPlatformKeyGenerationId(userId, generationId); } /** 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 3f5ac8e504b3..c73965024c55 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 @@ -322,19 +322,18 @@ public class RecoverableKeyStoreDb { /** * Sets the {@code generationId} of the platform key for user {@code userId}. * - * @return The primary key ID of the relation. + * @return The number of updated rows. */ public long setPlatformKeyGenerationId(int userId, int generationId) { SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(UserMetadataEntry.COLUMN_NAME_USER_ID, userId); values.put(UserMetadataEntry.COLUMN_NAME_PLATFORM_KEY_GENERATION_ID, generationId); - long result = db.replace( - UserMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null, values); - if (result != -1) { - invalidateKeysWithOldGenerationId(userId, generationId); - } - return result; + String selection = UserMetadataEntry.COLUMN_NAME_USER_ID + " = ?"; + String[] selectionArguments = new String[] {String.valueOf(userId)}; + + ensureUserMetadataEntryExists(userId); + return db.update(UserMetadataEntry.TABLE_NAME, values, selection, selectionArguments); } /** @@ -377,16 +376,19 @@ public class RecoverableKeyStoreDb { /** * Sets the {@code serialNumber} for the user {@code userId}. * - * @return The primary key of the inserted row, or -1 if failed. + * @return The number of updated rows. */ public long setUserSerialNumber(int userId, long serialNumber) { SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(UserMetadataEntry.COLUMN_NAME_USER_ID, userId); values.put(UserMetadataEntry.COLUMN_NAME_USER_SERIAL_NUMBER, serialNumber); - long result = db.replace( - UserMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null, values); - return result; + String selection = UserMetadataEntry.COLUMN_NAME_USER_ID + " = ?"; + String[] selectionArguments = new String[] {String.valueOf(userId)}; + + ensureUserMetadataEntryExists(userId); + return db.update(UserMetadataEntry.TABLE_NAME, values, selection, selectionArguments); + } /** @@ -1326,6 +1328,18 @@ public class RecoverableKeyStoreDb { } /** + * Creates an empty row in the user metadata table if such a row doesn't exist for + * the given userId, so db.update will succeed. + */ + private void ensureUserMetadataEntryExists(int userId) { + SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(UserMetadataEntry.COLUMN_NAME_USER_ID, userId); + db.insertWithOnConflict(UserMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null, + values, SQLiteDatabase.CONFLICT_IGNORE); + } + + /** * Closes all open connections to the database. */ public void close() { 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 932a769c86bc..bac8414ef205 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 @@ -305,6 +305,32 @@ public class RecoverableKeyStoreDbTest { } @Test + public void setUserSerialNumbers_keepsPlatformKeyGenerationId() { + int userId = 42; + int generationId = 110; + Long serialNumber = 10L; + + mRecoverableKeyStoreDb.setPlatformKeyGenerationId(userId, generationId); + mRecoverableKeyStoreDb.setUserSerialNumber(userId, serialNumber); + + assertEquals(generationId, mRecoverableKeyStoreDb.getPlatformKeyGenerationId(userId)); + } + + @Test + public void setPlatformKeyGenerationId_keepsUserSerialNumber() { + int userId = 42; + int generationId = 110; + Long serialNumber = 10L; + + mRecoverableKeyStoreDb.setPlatformKeyGenerationId(userId, generationId); + mRecoverableKeyStoreDb.setUserSerialNumber(userId, serialNumber); + mRecoverableKeyStoreDb.setPlatformKeyGenerationId(userId, generationId + 1); + + assertEquals(serialNumber, mRecoverableKeyStoreDb.getUserSerialNumbers().get(userId)); + } + + + @Test public void removeUserFromAllTables_removesData() throws Exception { int userId = 12; int generationId = 24; -- 2.11.0