diff --git a/bramble-android/src/main/java/org/briarproject/bramble/account/AndroidAccountManager.java b/bramble-android/src/main/java/org/briarproject/bramble/account/AndroidAccountManager.java index 2dfc57287..012f76c4b 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/account/AndroidAccountManager.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/account/AndroidAccountManager.java @@ -16,6 +16,7 @@ import java.util.Set; import java.util.logging.Logger; import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; import javax.inject.Inject; import static android.os.Build.VERSION.SDK_INT; @@ -73,7 +74,7 @@ class AndroidAccountManager extends AccountManagerImpl return PreferenceManager.getDefaultSharedPreferences(appContext); } - // Locking: stateChangeLock + @GuardedBy("stateChangeLock") private void deleteAppData(SharedPreferences... clear) { // Clear and commit shared preferences for (SharedPreferences prefs : clear) { diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoComponent.java index 9d498ec9d..95e89c2d0 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoComponent.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/CryptoComponent.java @@ -133,7 +133,8 @@ public interface CryptoComponent { * given password. The ciphertext will be decryptable using the same * password after the app restarts. */ - byte[] encryptWithPassword(byte[] plaintext, String password); + byte[] encryptWithPassword(byte[] plaintext, String password, + @Nullable KeyStoreConfig keyStoreConfig); /** * Decrypts and authenticates the given ciphertext that has been read from @@ -142,7 +143,8 @@ public interface CryptoComponent { * authenticated (for example, if the password is wrong). */ @Nullable - byte[] decryptWithPassword(byte[] ciphertext, String password); + byte[] decryptWithPassword(byte[] ciphertext, String password, + @Nullable KeyStoreConfig keyStoreConfig); /** * Encrypts the given plaintext to the given public key. diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/KeyStoreConfig.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/KeyStoreConfig.java new file mode 100644 index 000000000..f3c44740b --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/KeyStoreConfig.java @@ -0,0 +1,19 @@ +package org.briarproject.bramble.api.crypto; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import java.security.spec.AlgorithmParameterSpec; + +@NotNullByDefault +public interface KeyStoreConfig { + + String getKeyStoreType(); + + String getAlias(); + + String getProviderName(); + + String getMacAlgorithmName(); + + AlgorithmParameterSpec getParameterSpec(); +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseConfig.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseConfig.java index a01d12da5..bd916a9c6 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseConfig.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseConfig.java @@ -1,13 +1,19 @@ package org.briarproject.bramble.api.db; +import org.briarproject.bramble.api.crypto.KeyStoreConfig; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import java.io.File; +import javax.annotation.Nullable; + @NotNullByDefault public interface DatabaseConfig { File getDatabaseDirectory(); File getDatabaseKeyDirectory(); + + @Nullable + KeyStoreConfig getKeyStoreConfig(); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java index c4b75b6c3..351572215 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java @@ -19,6 +19,7 @@ import java.io.InputStreamReader; import java.util.logging.Logger; import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; import javax.inject.Inject; import static java.util.logging.Level.WARNING; @@ -68,9 +69,10 @@ class AccountManagerImpl implements AccountManager { return databaseKey; } - // Locking: stateChangeLock + // Package access for testing + @GuardedBy("stateChangeLock") @Nullable - protected String loadEncryptedDatabaseKey() { + String loadEncryptedDatabaseKey() { String key = readDbKeyFromFile(dbKeyFile); if (key == null) { LOG.info("No database key in primary file"); @@ -83,7 +85,7 @@ class AccountManagerImpl implements AccountManager { return key; } - // Locking: stateChangeLock + @GuardedBy("stateChangeLock") @Nullable private String readDbKeyFromFile(File f) { if (!f.exists()) { @@ -102,8 +104,9 @@ class AccountManagerImpl implements AccountManager { } } - // Locking: stateChangeLock - protected boolean storeEncryptedDatabaseKey(String hex) { + // Package access for testing + @GuardedBy("stateChangeLock") + boolean storeEncryptedDatabaseKey(String hex) { LOG.info("Storing database key in file"); // Create the directory if necessary if (databaseConfig.getDatabaseKeyDirectory().mkdirs()) @@ -140,7 +143,7 @@ class AccountManagerImpl implements AccountManager { } } - // Locking: stateChangeLock + @GuardedBy("stateChangeLock") private void writeDbKeyToFile(String key, File f) throws IOException { FileOutputStream out = new FileOutputStream(f); out.write(key.getBytes("UTF-8")); @@ -170,10 +173,11 @@ class AccountManagerImpl implements AccountManager { } } - // Locking: stateChangeLock + @GuardedBy("stateChangeLock") private boolean encryptAndStoreDatabaseKey(SecretKey key, String password) { byte[] plaintext = key.getBytes(); - byte[] ciphertext = crypto.encryptWithPassword(plaintext, password); + byte[] ciphertext = crypto.encryptWithPassword(plaintext, password, + databaseConfig.getKeyStoreConfig()); return storeEncryptedDatabaseKey(toHexString(ciphertext)); } @@ -197,7 +201,7 @@ class AccountManagerImpl implements AccountManager { } } - // Locking: stateChangeLock + @GuardedBy("stateChangeLock") @Nullable private SecretKey loadAndDecryptDatabaseKey(String password) { String hex = loadEncryptedDatabaseKey(); @@ -206,7 +210,8 @@ class AccountManagerImpl implements AccountManager { return null; } byte[] ciphertext = fromHexString(hex); - byte[] plaintext = crypto.decryptWithPassword(ciphertext, password); + byte[] plaintext = crypto.decryptWithPassword(ciphertext, password, + databaseConfig.getKeyStoreConfig()); if (plaintext == null) { LOG.info("Failed to decrypt database key"); return null; diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoComponentImpl.java index 37aa5de3d..2bf96007c 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoComponentImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/CryptoComponentImpl.java @@ -9,6 +9,7 @@ import org.briarproject.bramble.api.crypto.AgreementPublicKey; import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.KeyPair; import org.briarproject.bramble.api.crypto.KeyParser; +import org.briarproject.bramble.api.crypto.KeyStoreConfig; import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.SecretKey; @@ -24,7 +25,11 @@ import org.spongycastle.crypto.digests.Blake2bDigest; import org.whispersystems.curve25519.Curve25519; import org.whispersystems.curve25519.Curve25519KeyPair; +import java.io.IOException; import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.KeyStore.Entry; +import java.security.KeyStore.SecretKeyEntry; import java.security.NoSuchAlgorithmException; import java.security.Provider; import java.security.SecureRandom; @@ -32,12 +37,15 @@ import java.security.Security; import java.util.logging.Logger; import javax.annotation.Nullable; +import javax.crypto.KeyGenerator; +import javax.crypto.Mac; import javax.inject.Inject; import static java.lang.System.arraycopy; import static java.util.logging.Level.INFO; import static org.briarproject.bramble.api.crypto.CryptoConstants.KEY_TYPE_AGREEMENT; import static org.briarproject.bramble.api.crypto.CryptoConstants.KEY_TYPE_SIGNATURE; +import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull; import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES; import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.now; @@ -51,7 +59,8 @@ class CryptoComponentImpl implements CryptoComponent { private static final int SIGNATURE_KEY_PAIR_BITS = 256; private static final int STORAGE_IV_BYTES = 24; // 196 bits private static final int PBKDF_SALT_BYTES = 32; // 256 bits - private static final int PBKDF_FORMAT_SCRYPT = 0; + private static final byte PBKDF_FORMAT_SCRYPT = 0; + private static final byte PBKDF_FORMAT_SCRYPT_KEYSTORE = 1; private final SecureRandom secureRandom; private final PasswordBasedKdf passwordBasedKdf; @@ -311,7 +320,8 @@ class CryptoComponentImpl implements CryptoComponent { } @Override - public byte[] encryptWithPassword(byte[] input, String password) { + public byte[] encryptWithPassword(byte[] input, String password, + @Nullable KeyStoreConfig keyStoreConfig) { AuthenticatedCipher cipher = new XSalsa20Poly1305AuthenticatedCipher(); int macBytes = cipher.getMacBytes(); // Generate a random salt @@ -319,8 +329,10 @@ class CryptoComponentImpl implements CryptoComponent { secureRandom.nextBytes(salt); // Calibrate the KDF int cost = passwordBasedKdf.chooseCostParameter(); - // Derive the key from the password + // Derive the encryption key from the password SecretKey key = passwordBasedKdf.deriveKey(password, salt, cost); + if (keyStoreConfig != null) + key = requireNonNull(deriveKey(key, keyStoreConfig, true)); // Generate a random IV byte[] iv = new byte[STORAGE_IV_BYTES]; secureRandom.nextBytes(iv); @@ -331,7 +343,9 @@ class CryptoComponentImpl implements CryptoComponent { byte[] output = new byte[outputLen]; int outputOff = 0; // Format version - output[outputOff] = PBKDF_FORMAT_SCRYPT; + byte formatVersion = keyStoreConfig == null + ? PBKDF_FORMAT_SCRYPT : PBKDF_FORMAT_SCRYPT_KEYSTORE; + output[outputOff] = formatVersion; outputOff++; // Salt arraycopy(salt, 0, output, outputOff, salt.length); @@ -352,9 +366,53 @@ class CryptoComponentImpl implements CryptoComponent { } } + /** + * Derives a key from the given key and another key stored in a keystore. + * + * @param generateIfMissing Whether the stored key should be generated and + * stored if it doesn't already exist + * @return The derived key, or null if the stored key doesn't exist and + * {@code generateIfMissing} is false + */ + @Nullable + private SecretKey deriveKey(SecretKey key, KeyStoreConfig config, + boolean generateIfMissing) { + try { + // Load the keystore + KeyStore ks = KeyStore.getInstance(config.getKeyStoreType()); + ks.load(null); + // Load or generate the stored key + javax.crypto.SecretKey storedKey; + Entry e = ks.getEntry(config.getAlias(), null); + if (e == null) { + if (!generateIfMissing) { + LOG.warning("Key not found in keystore"); + return null; + } + KeyGenerator kg = KeyGenerator.getInstance( + config.getMacAlgorithmName(), config.getProviderName()); + kg.init(config.getParameterSpec()); + storedKey = kg.generateKey(); + LOG.info("Stored key in keystore"); + } else { + if (!(e instanceof SecretKeyEntry)) + throw new IllegalArgumentException(); + storedKey = ((SecretKeyEntry) e).getSecretKey(); + LOG.info("Loaded key from keystore"); + } + // Use the input key and the stored key to derive the output key + Mac mac = Mac.getInstance(config.getMacAlgorithmName()); + mac.init(storedKey); + return new SecretKey(mac.doFinal(key.getBytes())); + } catch (GeneralSecurityException | IOException e) { + throw new IllegalArgumentException(e); + } + } + @Override @Nullable - public byte[] decryptWithPassword(byte[] input, String password) { + public byte[] decryptWithPassword(byte[] input, String password, + @Nullable KeyStoreConfig keyStoreConfig) { AuthenticatedCipher cipher = new XSalsa20Poly1305AuthenticatedCipher(); int macBytes = cipher.getMacBytes(); // The input contains the format version, salt, cost parameter, IV, @@ -366,8 +424,13 @@ class CryptoComponentImpl implements CryptoComponent { // Format version byte formatVersion = input[inputOff]; inputOff++; - if (formatVersion != PBKDF_FORMAT_SCRYPT) - return null; // Unknown format + // Check whether we support this format version + if (formatVersion != PBKDF_FORMAT_SCRYPT && + formatVersion != PBKDF_FORMAT_SCRYPT_KEYSTORE) { + return null; + } + boolean useKeyStore = keyStoreConfig != null && + formatVersion == PBKDF_FORMAT_SCRYPT_KEYSTORE; // Salt byte[] salt = new byte[PBKDF_SALT_BYTES]; arraycopy(input, inputOff, salt, 0, salt.length); @@ -381,8 +444,12 @@ class CryptoComponentImpl implements CryptoComponent { byte[] iv = new byte[STORAGE_IV_BYTES]; arraycopy(input, inputOff, iv, 0, iv.length); inputOff += iv.length; - // Derive the key from the password + // Derive the decryption key from the password SecretKey key = passwordBasedKdf.deriveKey(password, salt, (int) cost); + if (useKeyStore) { + key = deriveKey(key, keyStoreConfig, false); + if (key == null) return null; + } // Initialise the cipher try { cipher.init(false, key, iv); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/account/AccountManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/account/AccountManagerImplTest.java index e1c1c1bb1..49fe8b202 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/account/AccountManagerImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/account/AccountManagerImplTest.java @@ -1,6 +1,7 @@ package org.briarproject.bramble.account; import org.briarproject.bramble.api.crypto.CryptoComponent; +import org.briarproject.bramble.api.crypto.KeyStoreConfig; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.identity.Identity; @@ -39,6 +40,8 @@ public class AccountManagerImplTest extends BrambleMockTestCase { private final DatabaseConfig databaseConfig = context.mock(DatabaseConfig.class); + private final KeyStoreConfig keyStoreConfig = + context.mock(KeyStoreConfig.class); private final CryptoComponent crypto = context.mock(CryptoComponent.class); private final IdentityManager identityManager = context.mock(IdentityManager.class); @@ -68,6 +71,8 @@ public class AccountManagerImplTest extends BrambleMockTestCase { will(returnValue(dbDir)); allowing(databaseConfig).getDatabaseKeyDirectory(); will(returnValue(keyDir)); + allowing(databaseConfig).getKeyStoreConfig(); + will(returnValue(keyStoreConfig)); }}); accountManager = @@ -89,7 +94,8 @@ public class AccountManagerImplTest extends BrambleMockTestCase { @Test public void testSignInReturnsFalseIfPasswordIsWrong() throws Exception { context.checking(new Expectations() {{ - oneOf(crypto).decryptWithPassword(encryptedKey, password); + oneOf(crypto).decryptWithPassword(encryptedKey, password, + keyStoreConfig); will(returnValue(null)); }}); @@ -109,7 +115,8 @@ public class AccountManagerImplTest extends BrambleMockTestCase { @Test public void testSignInReturnsTrueIfPasswordIsRight() throws Exception { context.checking(new Expectations() {{ - oneOf(crypto).decryptWithPassword(encryptedKey, password); + oneOf(crypto).decryptWithPassword(encryptedKey, password, + keyStoreConfig); will(returnValue(key.getBytes())); }}); @@ -258,7 +265,8 @@ public class AccountManagerImplTest extends BrambleMockTestCase { oneOf(identityManager).registerIdentity(identity); oneOf(crypto).generateSecretKey(); will(returnValue(key)); - oneOf(crypto).encryptWithPassword(key.getBytes(), password); + oneOf(crypto).encryptWithPassword(key.getBytes(), password, + keyStoreConfig); will(returnValue(encryptedKey)); }}); @@ -287,7 +295,8 @@ public class AccountManagerImplTest extends BrambleMockTestCase { public void testChangePasswordReturnsFalseIfPasswordIsWrong() throws Exception { context.checking(new Expectations() {{ - oneOf(crypto).decryptWithPassword(encryptedKey, password); + oneOf(crypto).decryptWithPassword(encryptedKey, password, + keyStoreConfig); will(returnValue(null)); }}); @@ -304,9 +313,11 @@ public class AccountManagerImplTest extends BrambleMockTestCase { public void testChangePasswordReturnsTrueIfPasswordIsRight() throws Exception { context.checking(new Expectations() {{ - oneOf(crypto).decryptWithPassword(encryptedKey, password); + oneOf(crypto).decryptWithPassword(encryptedKey, password, + keyStoreConfig); will(returnValue(key.getBytes())); - oneOf(crypto).encryptWithPassword(key.getBytes(), newPassword); + oneOf(crypto).encryptWithPassword(key.getBytes(), newPassword, + keyStoreConfig); will(returnValue(newEncryptedKey)); }}); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/PasswordBasedEncryptionTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/PasswordBasedEncryptionTest.java index 5efc3593e..e2380f655 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/PasswordBasedEncryptionTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/PasswordBasedEncryptionTest.java @@ -21,8 +21,8 @@ public class PasswordBasedEncryptionTest extends BrambleTestCase { public void testEncryptionAndDecryption() { byte[] input = TestUtils.getRandomBytes(1234); String password = "password"; - byte[] ciphertext = crypto.encryptWithPassword(input, password); - byte[] output = crypto.decryptWithPassword(ciphertext, password); + byte[] ciphertext = crypto.encryptWithPassword(input, password, null); + byte[] output = crypto.decryptWithPassword(ciphertext, password, null); assertArrayEquals(input, output); } @@ -30,11 +30,11 @@ public class PasswordBasedEncryptionTest extends BrambleTestCase { public void testInvalidCiphertextReturnsNull() { byte[] input = TestUtils.getRandomBytes(1234); String password = "password"; - byte[] ciphertext = crypto.encryptWithPassword(input, password); + byte[] ciphertext = crypto.encryptWithPassword(input, password, null); // Modify the ciphertext int position = new Random().nextInt(ciphertext.length); ciphertext[position] = (byte) (ciphertext[position] ^ 0xFF); - byte[] output = crypto.decryptWithPassword(ciphertext, password); + byte[] output = crypto.decryptWithPassword(ciphertext, password, null); assertNull(output); } } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/TestDatabaseConfig.java b/bramble-core/src/test/java/org/briarproject/bramble/test/TestDatabaseConfig.java index adf0712b1..f285f1c80 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/test/TestDatabaseConfig.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/test/TestDatabaseConfig.java @@ -1,10 +1,13 @@ package org.briarproject.bramble.test; +import org.briarproject.bramble.api.crypto.KeyStoreConfig; import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import java.io.File; +import javax.annotation.Nullable; + @NotNullByDefault public class TestDatabaseConfig implements DatabaseConfig { @@ -24,4 +27,10 @@ public class TestDatabaseConfig implements DatabaseConfig { public File getDatabaseKeyDirectory() { return keyDir; } + + @Nullable + @Override + public KeyStoreConfig getKeyStoreConfig() { + return null; + } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidDatabaseConfig.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidDatabaseConfig.java index f1fdc2492..c27cc2274 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AndroidDatabaseConfig.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidDatabaseConfig.java @@ -1,18 +1,26 @@ package org.briarproject.briar.android; +import org.briarproject.bramble.api.crypto.KeyStoreConfig; import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import java.io.File; +import javax.annotation.Nullable; + +import static android.os.Build.VERSION.SDK_INT; + @NotNullByDefault class AndroidDatabaseConfig implements DatabaseConfig { private final File dbDir, keyDir; + @Nullable + private final KeyStoreConfig keyStoreConfig; AndroidDatabaseConfig(File dbDir, File keyDir) { this.dbDir = dbDir; this.keyDir = keyDir; + keyStoreConfig = SDK_INT >= 23 ? new AndroidKeyStoreConfig() : null; } @Override @@ -24,4 +32,10 @@ class AndroidDatabaseConfig implements DatabaseConfig { public File getDatabaseKeyDirectory() { return keyDir; } + + @Nullable + @Override + public KeyStoreConfig getKeyStoreConfig() { + return keyStoreConfig; + } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidKeyStoreConfig.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidKeyStoreConfig.java new file mode 100644 index 000000000..752272c15 --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidKeyStoreConfig.java @@ -0,0 +1,52 @@ +package org.briarproject.briar.android; + +import android.security.keystore.KeyGenParameterSpec; + +import org.briarproject.bramble.api.crypto.KeyStoreConfig; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import java.security.spec.AlgorithmParameterSpec; + +import androidx.annotation.RequiresApi; + +import static android.security.keystore.KeyProperties.PURPOSE_SIGN; +import static android.security.keystore.KeyProperties.PURPOSE_VERIFY; + +@RequiresApi(23) +@NotNullByDefault +class AndroidKeyStoreConfig implements KeyStoreConfig { + + private final KeyGenParameterSpec spec; + + AndroidKeyStoreConfig() { + int purposes = PURPOSE_SIGN | PURPOSE_VERIFY; + spec = new KeyGenParameterSpec.Builder("db", purposes) + .setKeySize(256) + .build(); + } + + @Override + public String getKeyStoreType() { + return "AndroidKeyStore"; + } + + @Override + public String getAlias() { + return "db"; + } + + @Override + public String getProviderName() { + return "AndroidKeyStore"; + } + + @Override + public String getMacAlgorithmName() { + return "HmacSHA256"; + } + + @Override + public AlgorithmParameterSpec getParameterSpec() { + return spec; + } +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessDatabaseConfig.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessDatabaseConfig.kt index d7082e998..6dca9ae10 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessDatabaseConfig.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessDatabaseConfig.kt @@ -1,16 +1,15 @@ package org.briarproject.briar.headless +import org.briarproject.bramble.api.crypto.KeyStoreConfig import org.briarproject.bramble.api.db.DatabaseConfig import java.io.File internal class HeadlessDatabaseConfig(private val dbDir: File, private val keyDir: File) : DatabaseConfig { - override fun getDatabaseDirectory(): File { - return dbDir - } + override fun getDatabaseDirectory() = dbDir - override fun getDatabaseKeyDirectory(): File { - return keyDir - } + override fun getDatabaseKeyDirectory() = keyDir + + override fun getKeyStoreConfig(): KeyStoreConfig? = null }