Compare commits

...

1 Commits

Author SHA1 Message Date
akwizgran
0122282a72 Migrate away from hardware-backed keys until keymaster issues are fixed. 2020-08-14 16:57:09 +01:00
3 changed files with 20 additions and 20 deletions

View File

@@ -5,6 +5,9 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* Interface for strengthening a password-based key, for example by using a
* key stored in a key management service or hardware security module.
*
* TODO: Remove after a reasonable migration period unless we can work around
* Android keymaster bugs. Added 2020-02-24
*/
@NotNullByDefault
public interface KeyStrengthener {

View File

@@ -179,8 +179,9 @@ class AccountManagerImpl implements AccountManager {
@GuardedBy("stateChangeLock")
private boolean encryptAndStoreDatabaseKey(SecretKey key, String password) {
byte[] plaintext = key.getBytes();
byte[] ciphertext = crypto.encryptWithPassword(plaintext, password,
databaseConfig.getKeyStrengthener());
// Don't use a key strengthener as the Android keymaster isn't reliable
byte[] ciphertext =
crypto.encryptWithPassword(plaintext, password, null);
return storeEncryptedDatabaseKey(toHexString(ciphertext));
}
@@ -197,13 +198,13 @@ class AccountManagerImpl implements AccountManager {
@Override
public void signIn(String password) throws DecryptionException {
synchronized (stateChangeLock) {
databaseKey = loadAndDecryptDatabaseKey(password);
databaseKey = loadAndDecryptDatabaseKey(password, false);
}
}
@GuardedBy("stateChangeLock")
private SecretKey loadAndDecryptDatabaseKey(String password)
throws DecryptionException {
private SecretKey loadAndDecryptDatabaseKey(String password,
boolean changing) throws DecryptionException {
String hex = loadEncryptedDatabaseKey();
if (hex == null) {
LOG.warning("Failed to load encrypted database key");
@@ -214,11 +215,11 @@ class AccountManagerImpl implements AccountManager {
byte[] plaintext = crypto.decryptWithPassword(ciphertext, password,
keyStrengthener);
SecretKey key = new SecretKey(plaintext);
// If the DB key was encrypted with a weak key and a key strengthener
// is now available, re-encrypt the DB key with a strengthened key
if (keyStrengthener != null &&
!crypto.isEncryptedWithStrengthenedKey(ciphertext)) {
LOG.info("Re-encrypting database key with strengthened key");
// If the DB key was encrypted with a hardware-backed key, re-encrypt
// it without the hardware-backed key so keymaster bugs don't delete
// the user's account
if (!changing && crypto.isEncryptedWithStrengthenedKey(ciphertext)) {
LOG.info("Re-encrypting database key without strengthened key");
encryptAndStoreDatabaseKey(key, password);
}
return key;
@@ -228,7 +229,7 @@ class AccountManagerImpl implements AccountManager {
public void changePassword(String oldPassword, String newPassword)
throws DecryptionException {
synchronized (stateChangeLock) {
SecretKey key = loadAndDecryptDatabaseKey(oldPassword);
SecretKey key = loadAndDecryptDatabaseKey(oldPassword, true);
encryptAndStoreDatabaseKey(key, newPassword);
}
}

View File

@@ -134,7 +134,7 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
keyStrengthener);
will(returnValue(key.getBytes()));
oneOf(crypto).isEncryptedWithStrengthenedKey(encryptedKey);
will(returnValue(true));
will(returnValue(false));
}});
storeDatabaseKey(keyFile, encryptedKeyHex);
@@ -160,9 +160,8 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
keyStrengthener);
will(returnValue(key.getBytes()));
oneOf(crypto).isEncryptedWithStrengthenedKey(encryptedKey);
will(returnValue(false));
oneOf(crypto).encryptWithPassword(key.getBytes(), password,
keyStrengthener);
will(returnValue(true));
oneOf(crypto).encryptWithPassword(key.getBytes(), password, null);
will(returnValue(newEncryptedKey));
}});
@@ -262,8 +261,7 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
oneOf(identityManager).registerIdentity(identity);
oneOf(crypto).generateSecretKey();
will(returnValue(key));
oneOf(crypto).encryptWithPassword(key.getBytes(), password,
keyStrengthener);
oneOf(crypto).encryptWithPassword(key.getBytes(), password, null);
will(returnValue(encryptedKey));
}});
@@ -323,10 +321,8 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
oneOf(crypto).decryptWithPassword(encryptedKey, password,
keyStrengthener);
will(returnValue(key.getBytes()));
oneOf(crypto).isEncryptedWithStrengthenedKey(encryptedKey);
will(returnValue(true));
oneOf(crypto).encryptWithPassword(key.getBytes(), newPassword,
keyStrengthener);
null);
will(returnValue(newEncryptedKey));
}});