Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 942764e6 authored by Dmitry Dementyev's avatar Dmitry Dementyev Committed by Android (Google) Code Review
Browse files

Merge "Store badGuessCounter for remote lockscreen credentails check."

parents b75a0dfe 14392a1e
Loading
Loading
Loading
Loading
+60 −0
Original line number Diff line number Diff line
@@ -78,6 +78,18 @@ public class RecoverableKeyStoreDb {
        return new RecoverableKeyStoreDb(helper);
    }

    /**
     * A new instance, storing the database in the user directory of {@code context}.
     *
     * @hide
     */
    public static RecoverableKeyStoreDb newInstance(Context context, int version) {
        RecoverableKeyStoreDbHelper helper = new RecoverableKeyStoreDbHelper(context, version);
        helper.setWriteAheadLoggingEnabled(true);
        helper.setIdleConnectionTimeout(IDLE_TIMEOUT_SECONDS);
        return new RecoverableKeyStoreDb(helper);
    }

    private RecoverableKeyStoreDb(RecoverableKeyStoreDbHelper keyStoreDbHelper) {
        this.mKeyStoreDbHelper = keyStoreDbHelper;
        this.mTestOnlyInsecureCertificateHelper = new TestOnlyInsecureCertificateHelper();
@@ -389,7 +401,55 @@ public class RecoverableKeyStoreDb {

        ensureUserMetadataEntryExists(userId);
        return db.update(UserMetadataEntry.TABLE_NAME, values, selection, selectionArguments);
    }

    /**
     * Sets the {@code badGuessCounter} for the user {@code userId}.
     *
     * @return The number of updated rows.
     */
    public long setBadRemoteGuessCounter(int userId, int badGuessCounter) {
        SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(UserMetadataEntry.COLUMN_NAME_USER_ID, userId);
        values.put(UserMetadataEntry.COLUMN_NAME_BAD_REMOTE_GUESS_COUNTER, badGuessCounter);
        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);
    }

    /**
     * Returns the number of invalid remote lock screen guesses for the user {@code userId}.
     */
    public int getBadRemoteGuessCounter(int userId) {
        SQLiteDatabase db = mKeyStoreDbHelper.getReadableDatabase();
        String[] projection = {
                UserMetadataEntry.COLUMN_NAME_BAD_REMOTE_GUESS_COUNTER};
        String selection =
                UserMetadataEntry.COLUMN_NAME_USER_ID + " = ?";
        String[] selectionArguments = {
                Integer.toString(userId)};

        try (
            Cursor cursor = db.query(
                UserMetadataEntry.TABLE_NAME,
                projection,
                selection,
                selectionArguments,
                /*groupBy=*/ null,
                /*having=*/ null,
                /*orderBy=*/ null)
        ) {
            if (cursor.getCount() == 0) {
                return 0;
            }
            cursor.moveToFirst();
            return cursor.getInt(
                    cursor.getColumnIndexOrThrow(
                            UserMetadataEntry.COLUMN_NAME_BAD_REMOTE_GUESS_COUNTER));
        }
    }

    /**
+5 −0
Original line number Diff line number Diff line
@@ -98,6 +98,11 @@ class RecoverableKeyStoreDbContract {
         * Serial number for the user which can not be reused. Default value is {@code -1}.
         */
        static final String COLUMN_NAME_USER_SERIAL_NUMBER = "user_serial_number";

        /**
         * Number of invalid lockscreen credentials guess from a remote device.
         */
        static final String COLUMN_NAME_BAD_REMOTE_GUESS_COUNTER = "bad_remote_guess_counter";
    }

    /**
+42 −3
Original line number Diff line number Diff line
@@ -32,7 +32,10 @@ import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKe
class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper {
    private static final String TAG = "RecoverableKeyStoreDbHp";

    static final int DATABASE_VERSION = 6; // Added user id serial number.
    // v6 - added user id serial number.
    static final int DATABASE_VERSION = 6;
    // v7 - added bad guess counter for remote LSKF check;
    static final int DATABASE_VERSION_7 = 7;
    private static final String DATABASE_NAME = "recoverablekeystore.db";

    private static final String SQL_CREATE_KEYS_ENTRY =
@@ -57,6 +60,16 @@ class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper {
                    + UserMetadataEntry.COLUMN_NAME_PLATFORM_KEY_GENERATION_ID + " INTEGER,"
                    + UserMetadataEntry.COLUMN_NAME_USER_SERIAL_NUMBER + " INTEGER DEFAULT -1)";


    private static final String SQL_CREATE_USER_METADATA_ENTRY_FOR_V7 =
            "CREATE TABLE " + UserMetadataEntry.TABLE_NAME + "( "
                    + UserMetadataEntry._ID + " INTEGER PRIMARY KEY,"
                    + UserMetadataEntry.COLUMN_NAME_USER_ID + " INTEGER UNIQUE,"
                    + UserMetadataEntry.COLUMN_NAME_PLATFORM_KEY_GENERATION_ID + " INTEGER,"
                    + UserMetadataEntry.COLUMN_NAME_USER_SERIAL_NUMBER + " INTEGER DEFAULT -1,"
                    + UserMetadataEntry.COLUMN_NAME_BAD_REMOTE_GUESS_COUNTER
                    + " INTEGER DEFAULT 0)";

    private static final String SQL_CREATE_RECOVERY_SERVICE_METADATA_ENTRY =
            "CREATE TABLE " + RecoveryServiceMetadataEntry.TABLE_NAME + " ("
                    + RecoveryServiceMetadataEntry._ID + " INTEGER PRIMARY KEY,"
@@ -101,13 +114,26 @@ class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper {
            "DROP TABLE IF EXISTS " + RootOfTrustEntry.TABLE_NAME;

    RecoverableKeyStoreDbHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        super(context, DATABASE_NAME, null, getDbVersion(context));
    }

    RecoverableKeyStoreDbHelper(Context context, int version) {
        super(context, DATABASE_NAME, null, version);
    }

    private static int getDbVersion(Context context) {
        // TODO(b/254335492): Check flag
        return DATABASE_VERSION;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(SQL_CREATE_KEYS_ENTRY);
        if (db.getVersion() == 6) {
            db.execSQL(SQL_CREATE_USER_METADATA_ENTRY);
        } else {
            db.execSQL(SQL_CREATE_USER_METADATA_ENTRY_FOR_V7);
        }
        db.execSQL(SQL_CREATE_RECOVERY_SERVICE_METADATA_ENTRY);
        db.execSQL(SQL_CREATE_ROOT_OF_TRUST_ENTRY);
    }
@@ -147,6 +173,11 @@ class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper {
            oldVersion = 6;
        }

        if (oldVersion < 7 && newVersion >= 7) {
            upgradeDbForVersion7(db);
            oldVersion = 7;
        }

        if (oldVersion != newVersion) {
            Log.e(TAG, "Failed to update recoverablekeystore database to the most recent version");
        }
@@ -194,6 +225,14 @@ class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper {
                 /*defaultStr=*/ null);
    }

    private void upgradeDbForVersion7(SQLiteDatabase db) {
        Log.d(TAG, "Updating recoverable keystore database to version 7");
        addColumnToTable(db, UserMetadataEntry.TABLE_NAME,
                UserMetadataEntry.COLUMN_NAME_BAD_REMOTE_GUESS_COUNTER,
                "INTEGER DEFAULT 0",
                 /*defaultStr=*/ null);
    }

    private static void addColumnToTable(
            SQLiteDatabase db, String tableName, String column, String columnType,
            String defaultStr) {
+12 −5
Original line number Diff line number Diff line
@@ -104,7 +104,7 @@ public class RecoverableKeyStoreDbHelperTest {
    @Before
    public void setUp() throws Exception {
        Context context = InstrumentationRegistry.getTargetContext();
        mDatabaseHelper = new RecoverableKeyStoreDbHelper(context);
        mDatabaseHelper = new RecoverableKeyStoreDbHelper(context, 7);
        mDatabase = SQLiteDatabase.create(null);
    }

@@ -128,7 +128,7 @@ public class RecoverableKeyStoreDbHelperTest {
    @Test
    public void onUpgrade_beforeV2() throws Exception {
        mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 1,
                RecoverableKeyStoreDbHelper.DATABASE_VERSION);
                RecoverableKeyStoreDbHelper.DATABASE_VERSION_7);
        checkAllColumns_latest();
    }

@@ -136,7 +136,7 @@ public class RecoverableKeyStoreDbHelperTest {
    public void onUpgrade_fromV2() throws Exception {
        createV2Tables();
        mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 2,
                RecoverableKeyStoreDbHelper.DATABASE_VERSION);
                RecoverableKeyStoreDbHelper.DATABASE_VERSION_7);
        checkAllColumns_latest();
    }

@@ -153,8 +153,7 @@ public class RecoverableKeyStoreDbHelperTest {
        mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 3, /*newVersion=*/ 4);
        checkAllColumns_v4();

        mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 4,
                RecoverableKeyStoreDbHelper.DATABASE_VERSION);
        mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 4, /*newVersion=*/ 7);
        checkAllColumns_latest();
    }

@@ -243,6 +242,14 @@ public class RecoverableKeyStoreDbHelperTest {
        assertThat(
                mDatabase.replace(UserMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null, values))
                .isGreaterThan(-1L);

        // Bad guess counter was added when upgrading from v6 to v7
        values = new ContentValues();
        values.put(UserMetadataEntry.COLUMN_NAME_USER_ID, TEST_USER_ID);
        values.put(UserMetadataEntry.COLUMN_NAME_BAD_REMOTE_GUESS_COUNTER, 2);
        assertThat(
                mDatabase.replace(UserMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null, values))
                .isGreaterThan(-1L);
    }

}
+41 −2
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ public class RecoverableKeyStoreDbTest {
    public void setUp() {
        Context context = InstrumentationRegistry.getTargetContext();
        mDatabaseFile = context.getDatabasePath(DATABASE_FILE_NAME);
        mRecoverableKeyStoreDb = RecoverableKeyStoreDb.newInstance(context);
        mRecoverableKeyStoreDb = RecoverableKeyStoreDb.newInstance(context, 7);
    }

    @After
@@ -309,24 +309,63 @@ public class RecoverableKeyStoreDbTest {
        int userId = 42;
        int generationId = 110;
        Long serialNumber = 10L;
        int badGuessCounter = 3;

        mRecoverableKeyStoreDb.setPlatformKeyGenerationId(userId, generationId);
        mRecoverableKeyStoreDb.setBadRemoteGuessCounter(userId, badGuessCounter);
        mRecoverableKeyStoreDb.setUserSerialNumber(userId, serialNumber);

        assertEquals(badGuessCounter, mRecoverableKeyStoreDb.getBadRemoteGuessCounter(userId));
        assertEquals(generationId, mRecoverableKeyStoreDb.getPlatformKeyGenerationId(userId));
    }

    @Test
    public void getRemoteBadGuessCounter_returnsZeroAsDefaultValue() {
        assertEquals(0, mRecoverableKeyStoreDb.getBadRemoteGuessCounter(42));
    }

    @Test
    public void getRemoteBadGuessCounter_returnsStoredValue() {
        int userId = 42;
        int userId2 = 44;
        int badGuessCounter = 3;
        int badGuessCounter2 = 4;

        mRecoverableKeyStoreDb.setBadRemoteGuessCounter(userId, badGuessCounter);
        mRecoverableKeyStoreDb.setBadRemoteGuessCounter(userId2, badGuessCounter2);

        assertEquals(badGuessCounter, mRecoverableKeyStoreDb.getBadRemoteGuessCounter(userId));
        assertEquals(badGuessCounter2, mRecoverableKeyStoreDb.getBadRemoteGuessCounter(userId2));
    }

    @Test
    public void getBadRemoteGuessCounter_returnsStoredValue() {
        int userId = 42;
        int userId2 = 44;
        int badGuessCounter = 3;
        int badGuessCounter2 = 4;

        mRecoverableKeyStoreDb.setBadRemoteGuessCounter(userId, badGuessCounter);
        mRecoverableKeyStoreDb.setBadRemoteGuessCounter(userId2, badGuessCounter2);

        assertEquals(badGuessCounter, mRecoverableKeyStoreDb.getBadRemoteGuessCounter(userId));
        assertEquals(badGuessCounter2, mRecoverableKeyStoreDb.getBadRemoteGuessCounter(userId2));
    }

    @Test
    public void setPlatformKeyGenerationId_keepsUserSerialNumber() {
        int userId = 42;
        int generationId = 110;
        Long serialNumber = 10L;
        int badGuessCounter = 3;

        mRecoverableKeyStoreDb.setPlatformKeyGenerationId(userId, generationId);
        mRecoverableKeyStoreDb.setUserSerialNumber(userId, serialNumber);
        mRecoverableKeyStoreDb.setPlatformKeyGenerationId(userId, generationId + 1);
        mRecoverableKeyStoreDb.setBadRemoteGuessCounter(userId, badGuessCounter);

        assertEquals(serialNumber, mRecoverableKeyStoreDb.getUserSerialNumbers().get(userId));
        assertEquals(generationId, mRecoverableKeyStoreDb.getPlatformKeyGenerationId(userId));
        assertEquals(badGuessCounter, mRecoverableKeyStoreDb.getBadRemoteGuessCounter(userId));
    }

    @Test