Separate encryption key storage from device

Fixes: 147887130
Test: Unit tests pass and association successful

Change-Id: I99b91ce01a3dca6c376b0519ff42ae500266400f
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBlePeripheralManager.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBlePeripheralManager.java
index 7d085c5..4745fdb 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBlePeripheralManager.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBlePeripheralManager.java
@@ -30,7 +30,6 @@
 import android.bluetooth.le.AdvertiseData;
 import android.bluetooth.le.AdvertiseSettings;
 import android.car.encryptionrunner.EncryptionRunnerFactory;
-import android.car.encryptionrunner.Key;
 import android.os.ParcelUuid;
 
 import com.android.car.connecteddevice.AssociationCallback;
@@ -418,7 +417,7 @@
     private final SecureBleChannel.Callback mSecureChannelCallback =
             new SecureBleChannel.Callback() {
                 @Override
-                public void onSecureChannelEstablished(Key encryptionKey) {
+                public void onSecureChannelEstablished() {
                     BleDevice connectedDevice = getConnectedDevice();
                     if (connectedDevice == null || connectedDevice.mDeviceId == null) {
                         disconnectWithError("Null device id found when secure channel "
@@ -436,8 +435,7 @@
                                 + "association of that device for current user.");
                         mStorage.addAssociatedDeviceForActiveUser(
                                 new AssociatedDevice(deviceId, mClientDeviceAddress,
-                                        mClientDeviceName),
-                                encryptionKey.asBytes());
+                                        mClientDeviceName));
                         if (mAssociationCallback != null) {
                             mAssociationCallback.onAssociationCompleted(deviceId);
                             mAssociationCallback = null;
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/SecureBleChannel.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/SecureBleChannel.java
index 1730af8..a821186 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/SecureBleChannel.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/ble/SecureBleChannel.java
@@ -226,7 +226,7 @@
         mStorage.saveEncryptionKey(mDeviceId, newKey.asBytes());
         mEncryptionKey.set(newKey);
         sendServerAuthToClient(handshakeMessage.getNextMessage());
-        notifyCallback(callback -> callback.onSecureChannelEstablished(newKey));
+        notifyCallback(callback -> callback.onSecureChannelEstablished());
     }
 
     private void sendUniqueIdToClient() {
@@ -314,6 +314,7 @@
         }
 
         mState = message.getHandshakeState();
+        mStorage.saveEncryptionKey(mDeviceId, localKey.asBytes());
         mEncryptionKey.set(localKey);
         if (mDeviceId == null) {
             loge(TAG, "Unable to finish association, device id is null.");
@@ -322,7 +323,7 @@
         }
         logd(TAG, "Pairing code successfully verified and encryption key saved. Sending "
                 + "confirmation to device.");
-        notifyCallback(callback -> callback.onSecureChannelEstablished(localKey));
+        notifyCallback(Callback::onSecureChannelEstablished);
         DeviceMessage deviceMessage = new DeviceMessage(/* recipient = */ null,
                 /* isMessageEncrypted = */ false, CONFIRMATION_SIGNAL);
         mStream.writeMessage(deviceMessage, OperationType.ENCRYPTION_HANDSHAKE);
@@ -429,10 +430,8 @@
     interface Callback {
         /**
          * Invoked when secure channel has been established successfully.
-         *
-         * @param encryptionKey The new key generated in handshake.
          */
-        void onSecureChannelEstablished(Key encryptionKey);
+        void onSecureChannelEstablished();
 
         /**
          * Invoked when a {@link ChannelError} has been encountered in attempting to establish
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceDao.java b/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceDao.java
index a1fd6e1..c041d58 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceDao.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceDao.java
@@ -43,9 +43,24 @@
      * device id.
      */
     @Insert(onConflict = OnConflictStrategy.REPLACE)
-    void addOrUpdateAssociatedDevice(AssociatedDeviceEntity associatedDevice);
+    void addOrReplaceAssociatedDevice(AssociatedDeviceEntity associatedDevice);
 
     /** Remove a {@link AssociatedDeviceEntity}. */
     @Delete
     void removeAssociatedDevice(AssociatedDeviceEntity connectedDevice);
+
+    /** Get the key associated with a device id. */
+    @Query("SELECT * FROM associated_device_keys WHERE id LIKE :deviceId LIMIT 1")
+    AssociatedDeviceKeyEntity getAssociatedDeviceKey(String deviceId);
+
+    /**
+     * Add a {@link AssociatedDeviceKeyEntity}. Replace if a device key already exists with the
+     * same device id.
+     */
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    void addOrReplaceAssociatedDeviceKey(AssociatedDeviceKeyEntity keyEntity);
+
+    /** Remove a {@link AssociatedDeviceKeyEntity}. */
+    @Delete
+    void removeAssociatedDeviceKey(AssociatedDeviceKeyEntity keyEntity);
 }
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceEntity.java b/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceEntity.java
index c7a950e..cc97717 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceEntity.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceEntity.java
@@ -43,10 +43,6 @@
     @Nullable
     public String name;
 
-    /** Encrypted key for secure session. */
-    @NonNull
-    public String encryptedKey;
-
     public AssociatedDeviceEntity() { }
 
     public AssociatedDeviceEntity(int userId, AssociatedDevice associatedDevice) {
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceKeyEntity.java b/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceKeyEntity.java
new file mode 100644
index 0000000..6cd791f
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/storage/AssociatedDeviceKeyEntity.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.connecteddevice.storage;
+
+import androidx.annotation.NonNull;
+import androidx.room.Entity;
+import androidx.room.PrimaryKey;
+
+/** Table entity representing a key for an associated device. */
+@Entity(tableName = "associated_device_keys")
+public class AssociatedDeviceKeyEntity {
+
+    /** Id of the device. */
+    @PrimaryKey
+    @NonNull
+    public String id;
+
+    @NonNull
+    public String encryptedKey;
+
+    public AssociatedDeviceKeyEntity() { }
+
+    public AssociatedDeviceKeyEntity(String deviceId, String encryptedKey) {
+        id = deviceId;
+        this.encryptedKey = encryptedKey;
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceDatabase.java b/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceDatabase.java
index 42804b1..3671440 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceDatabase.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceDatabase.java
@@ -20,7 +20,8 @@
 import androidx.room.RoomDatabase;
 
 /** Database for connected devices. */
-@Database(entities = { AssociatedDeviceEntity.class }, version = 1, exportSchema = false)
+@Database(entities = { AssociatedDeviceEntity.class, AssociatedDeviceKeyEntity.class }, version = 1,
+        exportSchema = false)
 public abstract class ConnectedDeviceDatabase extends RoomDatabase {
     /** Return the DAO for the associated device table. */
     public abstract AssociatedDeviceDao associatedDeviceDao();
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceStorage.java b/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceStorage.java
index cc60e03..7b05981 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceStorage.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/storage/ConnectedDeviceStorage.java
@@ -116,8 +116,9 @@
      */
     @Nullable
     public byte[] getEncryptionKey(@NonNull String deviceId) {
-        AssociatedDeviceEntity entity = mAssociatedDeviceDatabase.getAssociatedDevice(deviceId);
-        if (entity == null || entity.encryptedKey == null) {
+        AssociatedDeviceKeyEntity entity =
+                mAssociatedDeviceDatabase.getAssociatedDeviceKey(deviceId);
+        if (entity == null) {
             logd(TAG, "Encryption key not found!");
             return null;
         }
@@ -141,13 +142,8 @@
      */
     public void saveEncryptionKey(@NonNull String deviceId, @NonNull byte[] encryptionKey) {
         String encryptedKey = encryptWithKeyStore(KEY_ALIAS, encryptionKey);
-        AssociatedDeviceEntity entity = mAssociatedDeviceDatabase.getAssociatedDevice(deviceId);
-        if (entity == null) {
-            entity = new AssociatedDeviceEntity();
-            entity.id = deviceId;
-        }
-        entity.encryptedKey = encryptedKey;
-        mAssociatedDeviceDatabase.addOrUpdateAssociatedDevice(entity);
+        AssociatedDeviceKeyEntity entity = new AssociatedDeviceKeyEntity(deviceId, encryptedKey);
+        mAssociatedDeviceDatabase.addOrReplaceAssociatedDeviceKey(entity);
         logd(TAG, "Successfully wrote encryption key.");
     }
 
@@ -362,11 +358,9 @@
      * Add the associated device of the given deviceId for the currently active user.
      *
      * @param device New associated device to be added.
-     * @param encryptionKey They encryption key used for association.
      */
-    public void addAssociatedDeviceForActiveUser(@NonNull AssociatedDevice device,
-            @NonNull byte[] encryptionKey) {
-        addAssociatedDeviceForUser(ActivityManager.getCurrentUser(), device, encryptionKey);
+    public void addAssociatedDeviceForActiveUser(@NonNull AssociatedDevice device) {
+        addAssociatedDeviceForUser(ActivityManager.getCurrentUser(), device);
         if (mAssociatedDeviceCallback != null) {
             mAssociatedDeviceCallback.onAssociatedDeviceAdded(device.getDeviceId());
         }
@@ -378,13 +372,10 @@
      *
      * @param userId The identifier of the user.
      * @param device New associated device to be added.
-     * @param encryptionKey They encryption key used for association.
      */
-    public void addAssociatedDeviceForUser(int userId, @NonNull AssociatedDevice device,
-            @NonNull byte[] encryptionKey) {
+    public void addAssociatedDeviceForUser(int userId, @NonNull AssociatedDevice device) {
         AssociatedDeviceEntity entity = new AssociatedDeviceEntity(userId, device);
-        entity.encryptedKey = encryptWithKeyStore(KEY_ALIAS, encryptionKey);
-        mAssociatedDeviceDatabase.addOrUpdateAssociatedDevice(entity);
+        mAssociatedDeviceDatabase.addOrReplaceAssociatedDevice(entity);
     }
 
     /**
@@ -401,7 +392,7 @@
             return;
         }
         entity.name = name;
-        mAssociatedDeviceDatabase.addOrUpdateAssociatedDevice(entity);
+        mAssociatedDeviceDatabase.addOrReplaceAssociatedDevice(entity);
         if (mAssociatedDeviceCallback != null) {
             mAssociatedDeviceCallback.onAssociatedDeviceUpdated(
                     new AssociatedDevice(deviceId, entity.address, name));
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/util/IdManager.kt b/connected-device-lib/src/com/android/car/connecteddevice/util/IdManager.kt
deleted file mode 100644
index 91d06b7..0000000
--- a/connected-device-lib/src/com/android/car/connecteddevice/util/IdManager.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.connecteddevice.util
-
-import com.android.internal.annotations.GuardedBy
-
-/** Class for managing unique numeric ids. */
-internal class IdManager {
-
-    private val lock = object
-    @Volatile
-    @GuardedBy("lock")
-    private var nextVal = 0
-
-    private var openVals = 0
-
-    /**
-     * Returns the next available id from the pool and reserves it from future use until released.
-     */
-    fun reserve(): Int {
-        synchronized(lock) {
-            return nextVal++
-        }
-    }
-
-    /** Release the [value] back to id pool. */
-    fun releaseReservation(value: Int) {
-        synchronized(lock) {
-            if (value == nextVal - 1) {
-                nextVal = value
-            } else {
-                openVals++
-            }
-            if (nextVal == openVals) {
-                nextVal = 0
-                openVals = 0
-            }
-        }
-    }
-}
\ No newline at end of file