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

Commit 584b923f authored by Bo Zhu's avatar Bo Zhu
Browse files

Write the integer given by setServerParameters() into SQLite DB

Change-Id: Icd8b40154560c600757d51ed4620d39fc07e494c
Test: adb shell am instrument -w -e package com.android.server.locksettings.recoverablekeystore com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
parent 5a4d8a1d
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -209,7 +209,7 @@ public class RecoverableKeyStoreLoader {
     * version. Version zero is used, if no snapshots were created for the account.
     *
     * @return Map from recovery agent accounts to snapshot versions.
     * @see KeyStoreRecoveryData.getSnapshotVersion
     * @see KeyStoreRecoveryData#getSnapshotVersion
     * @hide
     */
    public @NonNull Map<byte[], Integer> getRecoverySnapshotVersions()
@@ -231,7 +231,7 @@ public class RecoverableKeyStoreLoader {
    /**
     * Server parameters used to generate new recovery key blobs. This value will be included in
     * {@code KeyStoreRecoveryData.getEncryptedRecoveryKeyBlob()}. The same value must be included
     * in vaultParams {@link startRecoverySession}
     * in vaultParams {@link #startRecoverySession}
     *
     * @param serverParameters included in recovery key blob.
     * @see #getRecoveryData
+1 −1
Original line number Diff line number Diff line
@@ -184,7 +184,7 @@ public class RecoverableKeyStoreManager {

    public void setServerParameters(long serverParameters, int userId) throws RemoteException {
        checkRecoverKeyStorePermission();
        throw new UnsupportedOperationException();
        mDatabase.setServerParameters(userId, Binder.getCallingUid(), serverParameters);
    }

    /**
+118 −17
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ import android.util.Log;

import com.android.server.locksettings.recoverablekeystore.WrappedKey;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.KeysEntry;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServicePublicKeyEntry;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServiceMetadataEntry;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.UserMetadataEntry;


@@ -306,7 +306,7 @@ public class RecoverableKeyStoreDb {
    }

    /**
     * Inserts or updates the public key of the recovery service into the database.
     * Updates the public key of the recovery service into the database.
     *
     * @param userId The uid of the profile the application is running under.
     * @param uid The uid of the application to whom the key belongs.
@@ -318,11 +318,15 @@ public class RecoverableKeyStoreDb {
    public long setRecoveryServicePublicKey(int userId, int uid, PublicKey publicKey) {
        SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(RecoveryServicePublicKeyEntry.COLUMN_NAME_USER_ID, userId);
        values.put(RecoveryServicePublicKeyEntry.COLUMN_NAME_UID, uid);
        values.put(RecoveryServicePublicKeyEntry.COLUMN_NAME_PUBLIC_KEY, publicKey.getEncoded());
        return db.replace(RecoveryServicePublicKeyEntry.TABLE_NAME, /*nullColumnHack=*/ null,
                values);
        values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY, publicKey.getEncoded());
        String selection =
                RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " = ? AND "
                        + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + " = ?";
        String[] selectionArguments = {Integer.toString(userId), Integer.toString(uid)};

        ensureRecoveryServiceMetadataEntryExists(userId, uid);
        return db.update(
                RecoveryServiceMetadataEntry.TABLE_NAME, values, selection, selectionArguments);
    }

    /**
@@ -337,18 +341,18 @@ public class RecoverableKeyStoreDb {
        SQLiteDatabase db = mKeyStoreDbHelper.getReadableDatabase();

        String[] projection = {
                RecoveryServicePublicKeyEntry._ID,
                RecoveryServicePublicKeyEntry.COLUMN_NAME_USER_ID,
                RecoveryServicePublicKeyEntry.COLUMN_NAME_UID,
                RecoveryServicePublicKeyEntry.COLUMN_NAME_PUBLIC_KEY};
                RecoveryServiceMetadataEntry._ID,
                RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID,
                RecoveryServiceMetadataEntry.COLUMN_NAME_UID,
                RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY};
        String selection =
                RecoveryServicePublicKeyEntry.COLUMN_NAME_USER_ID + " = ? AND "
                        + RecoveryServicePublicKeyEntry.COLUMN_NAME_UID + " = ?";
                RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " = ? AND "
                        + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + " = ?";
        String[] selectionArguments = {Integer.toString(userId), Integer.toString(uid)};

        try (
                Cursor cursor = db.query(
                        RecoveryServicePublicKeyEntry.TABLE_NAME,
                        RecoveryServiceMetadataEntry.TABLE_NAME,
                        projection,
                        selection,
                        selectionArguments,
@@ -368,8 +372,12 @@ public class RecoverableKeyStoreDb {
                return null;
            }
            cursor.moveToFirst();
            byte[] keyBytes = cursor.getBlob(cursor.getColumnIndexOrThrow(
                    RecoveryServicePublicKeyEntry.COLUMN_NAME_PUBLIC_KEY));
            int idx = cursor.getColumnIndexOrThrow(
                    RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY);
            if (cursor.isNull(idx)) {
                return null;
            }
            byte[] keyBytes = cursor.getBlob(idx);
            X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(keyBytes);
            try {
                return KeyFactory.getInstance("EC").generatePublic(pkSpec);
@@ -387,6 +395,99 @@ public class RecoverableKeyStoreDb {
        }
    }

    /**
     * Updates the server parameters given by the application initializing the local recovery
     * components.
     *
     * @param userId The uid of the profile the application is running under.
     * @param uid The uid of the application.
     * @param serverParameters The server parameters.
     * @return The primary key of the inserted row, or -1 if failed.
     *
     * @hide
     */
    public long setServerParameters(int userId, int uid, long serverParameters) {
        SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMETERS, serverParameters);
        String selection =
                RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " = ? AND "
                        + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + " = ?";
        String[] selectionArguments = {Integer.toString(userId), Integer.toString(uid)};

        ensureRecoveryServiceMetadataEntryExists(userId, uid);
        return db.update(
                RecoveryServiceMetadataEntry.TABLE_NAME, values, selection, selectionArguments);
    }

    /**
     * Returns the server paramters that was previously set by the application who initialized the
     * local recovery service components.
     *
     * @param userId The uid of the profile the application is running under.
     * @param uid The uid of the application who initialized the local recovery components.
     * @return The server parameters that were previously set, or null if there's none.
     *
     * @hide
     */
    public Long getServerParameters(int userId, int uid) {
        SQLiteDatabase db = mKeyStoreDbHelper.getReadableDatabase();

        String[] projection = {
                RecoveryServiceMetadataEntry._ID,
                RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID,
                RecoveryServiceMetadataEntry.COLUMN_NAME_UID,
                RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMETERS};
        String selection =
                RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " = ? AND "
                        + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + " = ?";
        String[] selectionArguments = {Integer.toString(userId), Integer.toString(uid)};

        try (
                Cursor cursor = db.query(
                        RecoveryServiceMetadataEntry.TABLE_NAME,
                        projection,
                        selection,
                        selectionArguments,
                        /*groupBy=*/ null,
                        /*having=*/ null,
                        /*orderBy=*/ null)
        ) {
            int count = cursor.getCount();
            if (count == 0) {
                return null;
            }
            if (count > 1) {
                Log.wtf(TAG,
                        String.format(Locale.US,
                                "%d deviceId entries found for userId=%d uid=%d. "
                                        + "Should only ever be 0 or 1.", count, userId, uid));
                return null;
            }
            cursor.moveToFirst();
            int idx = cursor.getColumnIndexOrThrow(
                    RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMETERS);
            if (cursor.isNull(idx)) {
                return null;
            } else {
                return cursor.getLong(idx);
            }
        }
    }

    /**
     * Creates an empty row in the recovery service metadata table if such a row doesn't exist for
     * the given userId and uid, so db.update will succeed.
     */
    private void ensureRecoveryServiceMetadataEntryExists(int userId, int uid) {
        SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID, userId);
        values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_UID, uid);
        db.insertWithOnConflict(RecoveryServiceMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null,
                values, SQLiteDatabase.CONFLICT_IGNORE);
    }

    /**
     * Closes all open connections to the database.
     */
+8 −3
Original line number Diff line number Diff line
@@ -88,10 +88,10 @@ class RecoverableKeyStoreDbContract {
    }

    /**
     * Table holding public keys of the recovery service.
     * Table holding metadata of the recovery service.
     */
    static class RecoveryServicePublicKeyEntry implements BaseColumns {
        static final String TABLE_NAME = "recovery_service_public_keys";
    static class RecoveryServiceMetadataEntry implements BaseColumns {
        static final String TABLE_NAME = "recovery_service_metadata";

        /**
         * The user id of the profile the application is running under.
@@ -107,5 +107,10 @@ class RecoverableKeyStoreDbContract {
         * The public key of the recovery service.
         */
        static final String COLUMN_NAME_PUBLIC_KEY = "public_key";

        /**
         * The server parameters of the recovery service.
         */
        static final String COLUMN_NAME_SERVER_PARAMETERS = "server_parameters";
    }
}
+10 −9
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.KeysEntry;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServicePublicKeyEntry;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServiceMetadataEntry;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.UserMetadataEntry;

/**
@@ -36,14 +36,15 @@ class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper {
                    + UserMetadataEntry.COLUMN_NAME_PLATFORM_KEY_GENERATION_ID + " INTEGER)";

    private static final String SQL_CREATE_RECOVERY_SERVICE_PUBLIC_KEY_ENTRY =
            "CREATE TABLE " + RecoveryServicePublicKeyEntry.TABLE_NAME + " ("
                    + RecoveryServicePublicKeyEntry._ID + " INTEGER PRIMARY KEY,"
                    + RecoveryServicePublicKeyEntry.COLUMN_NAME_USER_ID + " INTEGER,"
                    + RecoveryServicePublicKeyEntry.COLUMN_NAME_UID + " INTEGER,"
                    + RecoveryServicePublicKeyEntry.COLUMN_NAME_PUBLIC_KEY + " BLOB,"
            "CREATE TABLE " + RecoveryServiceMetadataEntry.TABLE_NAME + " ("
                    + RecoveryServiceMetadataEntry._ID + " INTEGER PRIMARY KEY,"
                    + RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " INTEGER,"
                    + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + " INTEGER,"
                    + RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY + " BLOB,"
                    + RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMETERS + " INTEGER,"
                    + "UNIQUE("
                    + RecoveryServicePublicKeyEntry.COLUMN_NAME_USER_ID  + ","
                    + RecoveryServicePublicKeyEntry.COLUMN_NAME_UID + "))";
                    + RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID  + ","
                    + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + "))";

    private static final String SQL_DELETE_KEYS_ENTRY =
            "DROP TABLE IF EXISTS " + KeysEntry.TABLE_NAME;
@@ -52,7 +53,7 @@ class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper {
            "DROP TABLE IF EXISTS " + UserMetadataEntry.TABLE_NAME;

    private static final String SQL_DELETE_RECOVERY_SERVICE_PUBLIC_KEY_ENTRY =
            "DROP TABLE IF EXISTS " + RecoveryServicePublicKeyEntry.TABLE_NAME;
            "DROP TABLE IF EXISTS " + RecoveryServiceMetadataEntry.TABLE_NAME;

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