diff --git a/app/src/main/java/com/stevesoltys/seedvault/crypto/KeyManager.kt b/app/src/main/java/com/stevesoltys/seedvault/crypto/KeyManager.kt index 613d566a..60bbcbbf 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/crypto/KeyManager.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/crypto/KeyManager.kt @@ -24,7 +24,7 @@ internal const val KEY_ALIAS_MAIN = "com.stevesoltys.seedvault.main" private const val KEY_ALGORITHM_BACKUP = "AES" private const val KEY_ALGORITHM_MAIN = "HmacSHA256" -interface KeyManager { +interface KeyManager : org.calyxos.seedvault.core.crypto.KeyManager { /** * Store a new backup key derived from the given [seed]. * @@ -57,14 +57,6 @@ interface KeyManager { * because the key can not leave the [KeyStore]'s hardware security module. */ fun getBackupKey(): SecretKey - - /** - * Returns the main key, so it can be used for deriving sub-keys. - * - * Note that any attempt to export the key will return null or an empty [ByteArray], - * because the key can not leave the [KeyStore]'s hardware security module. - */ - fun getMainKey(): SecretKey } internal class KeyManagerImpl( diff --git a/app/src/main/java/com/stevesoltys/seedvault/plugins/webdav/WebDavFactory.kt b/app/src/main/java/com/stevesoltys/seedvault/plugins/webdav/WebDavFactory.kt index f11728e1..91a2d78c 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/plugins/webdav/WebDavFactory.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/plugins/webdav/WebDavFactory.kt @@ -8,12 +8,10 @@ package com.stevesoltys.seedvault.plugins.webdav import android.annotation.SuppressLint import android.content.Context import android.provider.Settings -import com.stevesoltys.seedvault.crypto.KeyManager import com.stevesoltys.seedvault.plugins.StoragePlugin class WebDavFactory( private val context: Context, - private val keyManager: KeyManager, ) { fun createAppStoragePlugin(config: WebDavConfig): StoragePlugin { @@ -27,7 +25,6 @@ class WebDavFactory( val androidId = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID) return com.stevesoltys.seedvault.storage.WebDavStoragePlugin( - keyManager = keyManager, androidId = androidId, webDavConfig = config, ) diff --git a/app/src/main/java/com/stevesoltys/seedvault/plugins/webdav/WebDavModule.kt b/app/src/main/java/com/stevesoltys/seedvault/plugins/webdav/WebDavModule.kt index 75181659..cc50a157 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/plugins/webdav/WebDavModule.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/plugins/webdav/WebDavModule.kt @@ -9,6 +9,6 @@ import org.koin.android.ext.koin.androidContext import org.koin.dsl.module val storagePluginModuleWebDav = module { - single { WebDavFactory(androidContext(), get()) } + single { WebDavFactory(androidContext()) } single { WebDavHandler(androidContext(), get(), get(), get()) } } diff --git a/app/src/main/java/com/stevesoltys/seedvault/storage/SeedvaultSafStoragePlugin.kt b/app/src/main/java/com/stevesoltys/seedvault/storage/SeedvaultSafStoragePlugin.kt index ac4c95ac..c484e4bc 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/storage/SeedvaultSafStoragePlugin.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/storage/SeedvaultSafStoragePlugin.kt @@ -11,7 +11,6 @@ import com.stevesoltys.seedvault.crypto.KeyManager import com.stevesoltys.seedvault.getStorageContext import com.stevesoltys.seedvault.plugins.saf.DocumentsStorage import org.calyxos.backup.storage.plugin.saf.SafStoragePlugin -import javax.crypto.SecretKey internal class SeedvaultSafStoragePlugin( private val appContext: Context, @@ -24,6 +23,4 @@ internal class SeedvaultSafStoragePlugin( override val context: Context get() = appContext.getStorageContext { storage.safStorage.isUsb } override val root: DocumentFile get() = storage.rootBackupDir ?: error("No storage set") - override fun getMasterKey(): SecretKey = keyManager.getMainKey() - override fun hasMasterKey(): Boolean = keyManager.hasMainKey() } diff --git a/app/src/main/java/com/stevesoltys/seedvault/storage/StorageModule.kt b/app/src/main/java/com/stevesoltys/seedvault/storage/StorageModule.kt index ff5e0b1d..4f229273 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/storage/StorageModule.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/storage/StorageModule.kt @@ -5,10 +5,11 @@ package com.stevesoltys.seedvault.storage +import com.stevesoltys.seedvault.crypto.KeyManager import com.stevesoltys.seedvault.plugins.StoragePluginManager import org.calyxos.backup.storage.api.StorageBackup import org.koin.dsl.module val storageModule = module { - single { StorageBackup(get(), { get().filesPlugin }) } + single { StorageBackup(get(), { get().filesPlugin }, get()) } } diff --git a/app/src/main/java/com/stevesoltys/seedvault/storage/WebDavStoragePlugin.kt b/app/src/main/java/com/stevesoltys/seedvault/storage/WebDavStoragePlugin.kt index 28241dee..e77a2a6d 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/storage/WebDavStoragePlugin.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/storage/WebDavStoragePlugin.kt @@ -11,7 +11,6 @@ import at.bitfire.dav4jvm.Response.HrefRelation.SELF import at.bitfire.dav4jvm.exception.NotFoundException import at.bitfire.dav4jvm.property.webdav.DisplayName import at.bitfire.dav4jvm.property.webdav.ResourceType -import com.stevesoltys.seedvault.crypto.KeyManager import com.stevesoltys.seedvault.plugins.chunkFolderRegex import com.stevesoltys.seedvault.plugins.webdav.DIRECTORY_ROOT import com.stevesoltys.seedvault.plugins.webdav.WebDavConfig @@ -26,12 +25,10 @@ import org.koin.core.time.measureDuration import java.io.IOException import java.io.InputStream import java.io.OutputStream -import javax.crypto.SecretKey import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine internal class WebDavStoragePlugin( - private val keyManager: KeyManager, /** * The result of Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID) */ @@ -121,9 +118,6 @@ internal class WebDavStoragePlugin( } } - override fun getMasterKey(): SecretKey = keyManager.getMainKey() - override fun hasMasterKey(): Boolean = keyManager.hasMainKey() - @Throws(IOException::class) override suspend fun getChunkOutputStream(chunkId: String): OutputStream { val chunkFolderName = chunkId.substring(0, 2) diff --git a/app/src/test/java/com/stevesoltys/seedvault/storage/WebDavStoragePluginTest.kt b/app/src/test/java/com/stevesoltys/seedvault/storage/WebDavStoragePluginTest.kt index 0118a092..c393d15d 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/storage/WebDavStoragePluginTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/storage/WebDavStoragePluginTest.kt @@ -5,12 +5,10 @@ package com.stevesoltys.seedvault.storage -import com.stevesoltys.seedvault.crypto.KeyManager import com.stevesoltys.seedvault.getRandomByteArray import com.stevesoltys.seedvault.getRandomString import com.stevesoltys.seedvault.plugins.webdav.WebDavTestConfig import com.stevesoltys.seedvault.transport.backup.BackupTest -import io.mockk.mockk import kotlinx.coroutines.runBlocking import org.calyxos.backup.storage.api.StoredSnapshot import org.junit.Assert.assertArrayEquals @@ -21,8 +19,7 @@ import java.io.IOException internal class WebDavStoragePluginTest : BackupTest() { - private val keyManager: KeyManager = mockk() - private val plugin = WebDavStoragePlugin(keyManager, "foo", WebDavTestConfig.getConfig()) + private val plugin = WebDavStoragePlugin("foo", WebDavTestConfig.getConfig()) private val snapshot = StoredSnapshot("foo.sv", System.currentTimeMillis()) @@ -85,7 +82,7 @@ internal class WebDavStoragePluginTest : BackupTest() { ) // other device writes another snapshot - val otherPlugin = WebDavStoragePlugin(keyManager, "bar", WebDavTestConfig.getConfig()) + val otherPlugin = WebDavStoragePlugin("bar", WebDavTestConfig.getConfig()) val otherSnapshot = StoredSnapshot("bar.sv", System.currentTimeMillis()) val otherSnapshotBytes = getRandomByteArray() assertEquals(emptyList(), otherPlugin.getAvailableChunkIds()) @@ -110,7 +107,6 @@ internal class WebDavStoragePluginTest : BackupTest() { @Test fun `test missing root dir`() = runBlocking { val plugin = WebDavStoragePlugin( - keyManager = keyManager, androidId = "foo", webDavConfig = WebDavTestConfig.getConfig(), root = getRandomString(), diff --git a/core/src/main/java/org/calyxos/seedvault/core/crypto/KeyManager.kt b/core/src/main/java/org/calyxos/seedvault/core/crypto/KeyManager.kt new file mode 100644 index 00000000..ec15fa31 --- /dev/null +++ b/core/src/main/java/org/calyxos/seedvault/core/crypto/KeyManager.kt @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2024 The Calyx Institute + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.calyxos.seedvault.core.crypto + +import java.security.KeyStore +import javax.crypto.SecretKey + +public interface KeyManager { + /** + * Returns the main key, so it can be used for deriving sub-keys. + * + * Note that any attempt to export the key will return null or an empty [ByteArray], + * because the key can not leave the [KeyStore]'s hardware security module. + */ + public fun getMainKey(): SecretKey +} diff --git a/storage/demo/build.gradle.kts b/storage/demo/build.gradle.kts index baa45faf..2317cae5 100644 --- a/storage/demo/build.gradle.kts +++ b/storage/demo/build.gradle.kts @@ -69,6 +69,7 @@ android { } dependencies { + implementation(project(":core")) implementation(project(":storage:lib")) implementation(libs.bundles.kotlin) diff --git a/storage/demo/src/main/java/de/grobox/storagebackuptester/App.kt b/storage/demo/src/main/java/de/grobox/storagebackuptester/App.kt index 5582b4ca..c534a2ef 100644 --- a/storage/demo/src/main/java/de/grobox/storagebackuptester/App.kt +++ b/storage/demo/src/main/java/de/grobox/storagebackuptester/App.kt @@ -9,6 +9,7 @@ import android.app.Application import android.os.StrictMode import android.os.StrictMode.VmPolicy import android.util.Log +import de.grobox.storagebackuptester.crypto.KeyManager import de.grobox.storagebackuptester.plugin.TestSafStoragePlugin import de.grobox.storagebackuptester.settings.SettingsManager import org.calyxos.backup.storage.api.StorageBackup @@ -19,7 +20,7 @@ class App : Application() { val settingsManager: SettingsManager by lazy { SettingsManager(applicationContext) } val storageBackup: StorageBackup by lazy { val plugin = TestSafStoragePlugin(this) { settingsManager.getBackupLocation() } - StorageBackup(this, { plugin }) + StorageBackup(this, { plugin }, KeyManager) } val fileSelectionManager: FileSelectionManager get() = FileSelectionManager() diff --git a/storage/demo/src/main/java/de/grobox/storagebackuptester/MainActivity.kt b/storage/demo/src/main/java/de/grobox/storagebackuptester/MainActivity.kt index c5619784..3b9347db 100644 --- a/storage/demo/src/main/java/de/grobox/storagebackuptester/MainActivity.kt +++ b/storage/demo/src/main/java/de/grobox/storagebackuptester/MainActivity.kt @@ -24,7 +24,7 @@ class MainActivity : AppCompatActivity() { KeyManager.storeMasterKey() - if (!KeyManager.hasMasterKey()) { + if (!KeyManager.hasMainKey()) { Log.e("TEST", "storing new key") KeyManager.storeMasterKey() } else { diff --git a/storage/demo/src/main/java/de/grobox/storagebackuptester/crypto/KeyManager.kt b/storage/demo/src/main/java/de/grobox/storagebackuptester/crypto/KeyManager.kt index 613aa51d..3a0e077a 100644 --- a/storage/demo/src/main/java/de/grobox/storagebackuptester/crypto/KeyManager.kt +++ b/storage/demo/src/main/java/de/grobox/storagebackuptester/crypto/KeyManager.kt @@ -14,7 +14,7 @@ import java.security.KeyStore import javax.crypto.SecretKey import javax.crypto.spec.SecretKeySpec -object KeyManager { +object KeyManager: org.calyxos.seedvault.core.crypto.KeyManager { private const val KEY_SIZE = 256 internal const val KEY_SIZE_BYTES = KEY_SIZE / 8 @@ -42,9 +42,9 @@ object KeyManager { keyStore.setEntry(KEY_ALIAS_MASTER, ksEntry, getKeyProtection()) } - fun hasMasterKey(): Boolean = keyStore.containsAlias(KEY_ALIAS_MASTER) + fun hasMainKey(): Boolean = keyStore.containsAlias(KEY_ALIAS_MASTER) - fun getMasterKey(): SecretKey { + override fun getMainKey(): SecretKey { val ksEntry = keyStore.getEntry(KEY_ALIAS_MASTER, null) as KeyStore.SecretKeyEntry return ksEntry.secretKey } diff --git a/storage/demo/src/main/java/de/grobox/storagebackuptester/plugin/TestSafStoragePlugin.kt b/storage/demo/src/main/java/de/grobox/storagebackuptester/plugin/TestSafStoragePlugin.kt index 10c41f9e..d9bfa24a 100644 --- a/storage/demo/src/main/java/de/grobox/storagebackuptester/plugin/TestSafStoragePlugin.kt +++ b/storage/demo/src/main/java/de/grobox/storagebackuptester/plugin/TestSafStoragePlugin.kt @@ -8,13 +8,10 @@ package de.grobox.storagebackuptester.plugin import android.content.Context import android.net.Uri import androidx.documentfile.provider.DocumentFile -import de.grobox.storagebackuptester.crypto.KeyManager import org.calyxos.backup.storage.plugin.saf.SafStoragePlugin import java.io.IOException import java.io.OutputStream -import javax.crypto.SecretKey -@Suppress("BlockingMethodInNonBlockingContext") class TestSafStoragePlugin( appContext: Context, private val getLocationUri: () -> Uri?, @@ -33,14 +30,6 @@ class TestSafStoragePlugin( } } - override fun getMasterKey(): SecretKey { - return KeyManager.getMasterKey() - } - - override fun hasMasterKey(): Boolean { - return KeyManager.hasMasterKey() - } - @Throws(IOException::class) override suspend fun getChunkOutputStream(chunkId: String): OutputStream { if (getLocationUri() == null) return nullStream diff --git a/storage/lib/build.gradle.kts b/storage/lib/build.gradle.kts index 9d1ba5d3..5ada1faa 100644 --- a/storage/lib/build.gradle.kts +++ b/storage/lib/build.gradle.kts @@ -81,6 +81,7 @@ android { } dependencies { + implementation(project(":core")) implementation(libs.bundles.kotlin) implementation(libs.androidx.core) implementation(libs.androidx.fragment) diff --git a/storage/lib/src/main/java/org/calyxos/backup/storage/api/StorageBackup.kt b/storage/lib/src/main/java/org/calyxos/backup/storage/api/StorageBackup.kt index d2ed1855..7ffe459c 100644 --- a/storage/lib/src/main/java/org/calyxos/backup/storage/api/StorageBackup.kt +++ b/storage/lib/src/main/java/org/calyxos/backup/storage/api/StorageBackup.kt @@ -31,6 +31,7 @@ import org.calyxos.backup.storage.scanner.DocumentScanner import org.calyxos.backup.storage.scanner.FileScanner import org.calyxos.backup.storage.scanner.MediaScanner import org.calyxos.backup.storage.toStoredUri +import org.calyxos.seedvault.core.crypto.KeyManager import java.io.IOException import java.util.concurrent.atomic.AtomicBoolean @@ -39,6 +40,7 @@ private const val TAG = "StorageBackup" public class StorageBackup( private val context: Context, private val pluginGetter: () -> StoragePlugin, + private val keyManager: KeyManager, private val dispatcher: CoroutineDispatcher = Dispatchers.IO, ) { @@ -54,13 +56,16 @@ public class StorageBackup( private val backup by lazy { val documentScanner = DocumentScanner(context) val fileScanner = FileScanner(uriStore, mediaScanner, documentScanner) - Backup(context, db, fileScanner, pluginGetter, chunksCacheRepopulater) + Backup(context, db, fileScanner, pluginGetter, keyManager, chunksCacheRepopulater) } private val restore by lazy { - Restore(context, pluginGetter, snapshotRetriever, FileRestore(context, mediaScanner)) + val fileRestore = FileRestore(context, mediaScanner) + Restore(context, pluginGetter, keyManager, snapshotRetriever, fileRestore) } private val retention = RetentionManager(context) - private val pruner by lazy { Pruner(db, retention, pluginGetter, snapshotRetriever) } + private val pruner by lazy { + Pruner(db, retention, pluginGetter, keyManager, snapshotRetriever) + } private val backupRunning = AtomicBoolean(false) private val restoreRunning = AtomicBoolean(false) diff --git a/storage/lib/src/main/java/org/calyxos/backup/storage/api/StoragePlugin.kt b/storage/lib/src/main/java/org/calyxos/backup/storage/api/StoragePlugin.kt index a796b881..0a6677f7 100644 --- a/storage/lib/src/main/java/org/calyxos/backup/storage/api/StoragePlugin.kt +++ b/storage/lib/src/main/java/org/calyxos/backup/storage/api/StoragePlugin.kt @@ -8,8 +8,6 @@ package org.calyxos.backup.storage.api import java.io.IOException import java.io.InputStream import java.io.OutputStream -import java.security.KeyStore -import javax.crypto.SecretKey public interface StoragePlugin { @@ -28,16 +26,6 @@ public interface StoragePlugin { @Throws(IOException::class) public suspend fun getAvailableChunkIds(): List - /** - * Returns a [SecretKey] for HmacSHA256, ideally stored in the [KeyStore]. - */ - public fun getMasterKey(): SecretKey - - /** - * Returns true if the key for [getMasterKey] exists, false otherwise. - */ - public fun hasMasterKey(): Boolean - @Throws(IOException::class) public suspend fun getChunkOutputStream(chunkId: String): OutputStream @@ -48,8 +36,7 @@ public interface StoragePlugin { /** * Returns *all* [StoredSnapshot]s that are available on storage - * independent of user ID and whether they can be decrypted - * with the key returned by [getMasterKey]. + * independent of user ID and whether they can be decrypted with the main key. */ @Throws(IOException::class) public suspend fun getBackupSnapshotsForRestore(): List diff --git a/storage/lib/src/main/java/org/calyxos/backup/storage/backup/Backup.kt b/storage/lib/src/main/java/org/calyxos/backup/storage/backup/Backup.kt index 545353ab..cda7c8ea 100644 --- a/storage/lib/src/main/java/org/calyxos/backup/storage/backup/Backup.kt +++ b/storage/lib/src/main/java/org/calyxos/backup/storage/backup/Backup.kt @@ -19,6 +19,7 @@ import org.calyxos.backup.storage.db.Db import org.calyxos.backup.storage.measure import org.calyxos.backup.storage.scanner.FileScanner import org.calyxos.backup.storage.scanner.FileScannerResult +import org.calyxos.seedvault.core.crypto.KeyManager import java.io.IOException import java.security.GeneralSecurityException import kotlin.time.Duration @@ -42,6 +43,7 @@ internal class Backup( private val db: Db, private val fileScanner: FileScanner, private val storagePluginGetter: () -> StoragePlugin, + keyManager: KeyManager, private val cacheRepopulater: ChunksCacheRepopulater, chunkSizeMax: Int = CHUNK_SIZE_MAX, private val streamCrypto: StreamCrypto = StreamCrypto, @@ -60,12 +62,12 @@ internal class Backup( private val chunksCache = db.getChunksCache() private val mac = try { - ChunkCrypto.getMac(ChunkCrypto.deriveChunkIdKey(storagePlugin.getMasterKey())) + ChunkCrypto.getMac(ChunkCrypto.deriveChunkIdKey(keyManager.getMainKey())) } catch (e: GeneralSecurityException) { throw AssertionError(e) } private val streamKey = try { - streamCrypto.deriveStreamKey(storagePlugin.getMasterKey()) + streamCrypto.deriveStreamKey(keyManager.getMainKey()) } catch (e: GeneralSecurityException) { throw AssertionError(e) } diff --git a/storage/lib/src/main/java/org/calyxos/backup/storage/prune/Pruner.kt b/storage/lib/src/main/java/org/calyxos/backup/storage/prune/Pruner.kt index c6c91f35..dc6100b7 100644 --- a/storage/lib/src/main/java/org/calyxos/backup/storage/prune/Pruner.kt +++ b/storage/lib/src/main/java/org/calyxos/backup/storage/prune/Pruner.kt @@ -13,6 +13,7 @@ import org.calyxos.backup.storage.crypto.StreamCrypto import org.calyxos.backup.storage.db.Db import org.calyxos.backup.storage.measure import org.calyxos.backup.storage.plugin.SnapshotRetriever +import org.calyxos.seedvault.core.crypto.KeyManager import java.io.IOException import java.security.GeneralSecurityException import kotlin.time.ExperimentalTime @@ -23,6 +24,7 @@ internal class Pruner( private val db: Db, private val retentionManager: RetentionManager, private val storagePluginGetter: () -> StoragePlugin, + keyManager: KeyManager, private val snapshotRetriever: SnapshotRetriever, streamCrypto: StreamCrypto = StreamCrypto, ) { @@ -30,7 +32,7 @@ internal class Pruner( private val storagePlugin get() = storagePluginGetter() private val chunksCache = db.getChunksCache() private val streamKey = try { - streamCrypto.deriveStreamKey(storagePlugin.getMasterKey()) + streamCrypto.deriveStreamKey(keyManager.getMainKey()) } catch (e: GeneralSecurityException) { throw AssertionError(e) } diff --git a/storage/lib/src/main/java/org/calyxos/backup/storage/restore/Restore.kt b/storage/lib/src/main/java/org/calyxos/backup/storage/restore/Restore.kt index 13e6609d..b8507727 100644 --- a/storage/lib/src/main/java/org/calyxos/backup/storage/restore/Restore.kt +++ b/storage/lib/src/main/java/org/calyxos/backup/storage/restore/Restore.kt @@ -19,6 +19,7 @@ import org.calyxos.backup.storage.backup.BackupSnapshot import org.calyxos.backup.storage.crypto.StreamCrypto import org.calyxos.backup.storage.measure import org.calyxos.backup.storage.plugin.SnapshotRetriever +import org.calyxos.seedvault.core.crypto.KeyManager import java.io.IOException import java.io.InputStream import java.security.GeneralSecurityException @@ -28,6 +29,7 @@ private const val TAG = "Restore" internal class Restore( context: Context, private val storagePluginGetter: () -> StoragePlugin, + private val keyManager: KeyManager, private val snapshotRetriever: SnapshotRetriever, fileRestore: FileRestore, streamCrypto: StreamCrypto = StreamCrypto, @@ -39,7 +41,7 @@ internal class Restore( // so we need to get it lazily here to prevent crashes. We can still crash later, // if the plugin is not providing a key as it should when performing calls into this class. try { - streamCrypto.deriveStreamKey(storagePlugin.getMasterKey()) + streamCrypto.deriveStreamKey(keyManager.getMainKey()) } catch (e: GeneralSecurityException) { throw AssertionError(e) } diff --git a/storage/lib/src/test/java/org/calyxos/backup/storage/BackupRestoreTest.kt b/storage/lib/src/test/java/org/calyxos/backup/storage/BackupRestoreTest.kt index dd53e98c..7ab64db2 100644 --- a/storage/lib/src/test/java/org/calyxos/backup/storage/BackupRestoreTest.kt +++ b/storage/lib/src/test/java/org/calyxos/backup/storage/BackupRestoreTest.kt @@ -46,6 +46,7 @@ import org.calyxos.backup.storage.restore.RestorableFile import org.calyxos.backup.storage.restore.Restore import org.calyxos.backup.storage.scanner.FileScanner import org.calyxos.backup.storage.scanner.FileScannerResult +import org.calyxos.seedvault.core.crypto.KeyManager import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue @@ -71,6 +72,7 @@ internal class BackupRestoreTest { private val fileScanner: FileScanner = mockk() private val pluginGetter: () -> StoragePlugin = mockk() + private val keyManager: KeyManager = mockk() private val plugin: StoragePlugin = mockk() private val fileRestore: FileRestore = mockk() private val snapshotRetriever = SnapshotRetriever(pluginGetter) @@ -87,7 +89,7 @@ internal class BackupRestoreTest { every { pluginGetter() } returns plugin every { db.getFilesCache() } returns filesCache every { db.getChunksCache() } returns chunksCache - every { plugin.getMasterKey() } returns SecretKeySpec( + every { keyManager.getMainKey() } returns SecretKeySpec( "This is a backup key for testing".toByteArray(), 0, KEY_SIZE_BYTES, ALGORITHM_HMAC ) @@ -95,11 +97,11 @@ internal class BackupRestoreTest { every { context.contentResolver } returns contentResolver } - private val restore = Restore(context, pluginGetter, snapshotRetriever, fileRestore) + private val restore = Restore(context, pluginGetter, keyManager, snapshotRetriever, fileRestore) @Test fun testZipAndSingleRandom(): Unit = runBlocking { - val backup = Backup(context, db, fileScanner, pluginGetter, cacheRepopulater) + val backup = Backup(context, db, fileScanner, pluginGetter, keyManager, cacheRepopulater) val smallFileMBytes = Random.nextBytes(Random.nextInt(SMALL_FILE_SIZE_MAX)) val smallFileM = getRandomMediaFile(smallFileMBytes.size) @@ -236,7 +238,8 @@ internal class BackupRestoreTest { @Test fun testMultiChunks(): Unit = runBlocking { - val backup = Backup(context, db, fileScanner, pluginGetter, cacheRepopulater, 4) + val backup = + Backup(context, db, fileScanner, pluginGetter, keyManager, cacheRepopulater, 4) val chunk1 = byteArrayOf(0x00, 0x01, 0x02, 0x03) val chunk2 = byteArrayOf(0x04, 0x05, 0x06, 0x07) diff --git a/storage/lib/src/test/java/org/calyxos/backup/storage/prune/PrunerTest.kt b/storage/lib/src/test/java/org/calyxos/backup/storage/prune/PrunerTest.kt index 7da12a29..678f93e6 100644 --- a/storage/lib/src/test/java/org/calyxos/backup/storage/prune/PrunerTest.kt +++ b/storage/lib/src/test/java/org/calyxos/backup/storage/prune/PrunerTest.kt @@ -26,6 +26,7 @@ import org.calyxos.backup.storage.db.Db import org.calyxos.backup.storage.getRandomString import org.calyxos.backup.storage.mockLog import org.calyxos.backup.storage.plugin.SnapshotRetriever +import org.calyxos.seedvault.core.crypto.KeyManager import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test @@ -37,6 +38,7 @@ internal class PrunerTest { private val db: Db = mockk() private val chunksCache: ChunksCache = mockk() private val pluginGetter: () -> StoragePlugin = mockk() + private val keyManager: KeyManager = mockk() private val plugin: StoragePlugin = mockk() private val snapshotRetriever: SnapshotRetriever = mockk() private val retentionManager: RetentionManager = mockk() @@ -48,11 +50,12 @@ internal class PrunerTest { mockLog(false) every { pluginGetter() } returns plugin every { db.getChunksCache() } returns chunksCache - every { plugin.getMasterKey() } returns masterKey + every { keyManager.getMainKey() } returns masterKey every { streamCrypto.deriveStreamKey(masterKey) } returns streamKey } - private val pruner = Pruner(db, retentionManager, pluginGetter, snapshotRetriever, streamCrypto) + private val pruner = + Pruner(db, retentionManager, pluginGetter, keyManager, snapshotRetriever, streamCrypto) @Test fun test() = runBlocking {