@ -1,8 +1,10 @@
package com.beemdevelopment.aegis.ui.tasks ;
import android.app.ProgressDialog ;
import android.content.Context ;
import com.beemdevelopment.aegis.R ;
import com.beemdevelopment.aegis.crypto.CryptoUtils ;
import com.beemdevelopment.aegis.crypto.MasterKey ;
import com.beemdevelopment.aegis.db.slots.FingerprintSlot ;
import com.beemdevelopment.aegis.db.slots.PasswordSlot ;
@ -14,7 +16,7 @@ import com.beemdevelopment.aegis.db.slots.SlotList;
import javax.crypto.Cipher ;
import javax.crypto.SecretKey ;
public class SlotListTask < T extends Slot > extends ProgressDialogTask < SlotListTask . Params , MasterKey > {
public class SlotListTask < T extends Slot > extends ProgressDialogTask < SlotListTask . Params , SlotListTask. Result > {
private Callback _cb ;
private Class < T > _type ;
@ -25,51 +27,77 @@ public class SlotListTask<T extends Slot> extends ProgressDialogTask<SlotListTas
}
@Override
protected MasterKey doInBackground ( SlotListTask . Params . . . args ) {
protected Result doInBackground ( SlotListTask . Params . . . args ) {
setPriority ( ) ;
Params params = args [ 0 ] ;
SlotList slots = params . getSlots ( ) ;
try {
if ( ! slots . has ( _type ) ) {
throw new RuntimeException ( ) ;
}
MasterKey masterKey = null ;
for ( Slot slot : slots . findAll ( _type ) ) {
try {
if ( slot instanceof PasswordSlot ) {
char [ ] password = ( char [ ] ) params . getObj ( ) ;
SecretKey key = ( ( PasswordSlot ) slot ) . deriveKey ( password ) ;
Cipher cipher = slot . createDecryptCipher ( key ) ;
masterKey = slot . getKey ( cipher ) ;
} else if ( slot instanceof FingerprintSlot ) {
masterKey = slot . getKey ( ( Cipher ) params . getObj ( ) ) ;
} else {
throw new RuntimeException ( ) ;
}
break ;
} catch ( SlotIntegrityException e ) {
for ( Slot slot : slots . findAll ( _type ) ) {
try {
if ( slot instanceof PasswordSlot ) {
char [ ] password = ( char [ ] ) params . getObj ( ) ;
return decryptPasswordSlot ( ( PasswordSlot ) slot , password ) ;
} else if ( slot instanceof FingerprintSlot ) {
return decryptFingerprintSlot ( ( FingerprintSlot ) slot , ( Cipher ) params . getObj ( ) ) ;
}
}
} catch ( SlotException e ) {
throw new RuntimeException ( e ) ;
} catch ( SlotIntegrityException ignored ) {
if ( masterKey = = null ) {
throw new SlotIntegrityException ( ) ;
}
}
return masterKey ;
} catch ( SlotIntegrityException e ) {
return null ;
} catch ( SlotException e ) {
throw new RuntimeException ( e ) ;
return null ;
}
private Result decryptFingerprintSlot ( FingerprintSlot slot , Cipher cipher )
throws SlotException , SlotIntegrityException {
MasterKey key = slot . getKey ( cipher ) ;
return new Result ( key , slot ) ;
}
private Result decryptPasswordSlot ( PasswordSlot slot , char [ ] password )
throws SlotIntegrityException , SlotException {
MasterKey masterKey ;
SecretKey key = slot . deriveKey ( password ) ;
// a bug introduced in afb9e59 caused 64-byte passwords to produce a different key than before
// so, try the old password encode function if the encoded password is longer than 64 bytes
byte [ ] oldPasswordBytes = CryptoUtils . toBytesOld ( password ) ;
if ( ! slot . isRepaired ( ) & & oldPasswordBytes . length > 64 ) {
ProgressDialog dialog = getDialog ( ) ;
dialog . setMessage ( dialog . getContext ( ) . getString ( R . string . unlocking_vault_repair ) ) ;
// try to decrypt the password slot with the old key
SecretKey oldKey = slot . deriveKey ( oldPasswordBytes ) ;
masterKey = decryptPasswordSlot ( slot , oldKey ) ;
} else {
masterKey = decryptPasswordSlot ( slot , key ) ;
}
// if necessary, repair the slot by re-encrypting the master key with the correct key
// slots with passwords smaller than 64 bytes also get this treatment to make sure those also have 'repaired' set to true
boolean repaired = false ;
if ( ! slot . isRepaired ( ) ) {
Cipher cipher = Slot . createEncryptCipher ( key ) ;
slot . setKey ( masterKey , cipher ) ;
repaired = true ;
}
return new Result ( masterKey , slot , repaired ) ;
}
private MasterKey decryptPasswordSlot ( PasswordSlot slot , SecretKey key )
throws SlotException , SlotIntegrityException {
Cipher cipher = slot . createDecryptCipher ( key ) ;
return slot . getKey ( cipher ) ;
}
@Override
protected void onPostExecute ( MasterKey masterKey ) {
super . onPostExecute ( masterKey ) ;
_cb . onTaskFinished ( masterKey ) ;
protected void onPostExecute ( Result result ) {
super . onPostExecute ( result ) ;
_cb . onTaskFinished ( result ) ;
}
public static class Params {
@ -90,7 +118,35 @@ public class SlotListTask<T extends Slot> extends ProgressDialogTask<SlotListTas
}
}
public static class Result {
private MasterKey _key ;
private Slot _slot ;
private boolean _repaired ;
public Result ( MasterKey key , Slot slot , boolean repaired ) {
_key = key ;
_slot = slot ;
_repaired = repaired ;
}
public Result ( MasterKey key , Slot slot ) {
this ( key , slot , false ) ;
}
public MasterKey getKey ( ) {
return _key ;
}
public Slot getSlot ( ) {
return _slot ;
}
public boolean isSlotRepaired ( ) {
return _repaired ;
}
}
public interface Callback {
void onTaskFinished ( MasterKey key ) ;
void onTaskFinished ( Result result ) ;
}
}