diff --git a/briar-android/src/net/sf/briar/android/AndroidModule.java b/briar-android/src/net/sf/briar/android/AndroidModule.java index 83ec34737014019708dcf2a0e0dcbeea57c9a106..d379f5086cc32b26583e3db7571a735aa3206452 100644 --- a/briar-android/src/net/sf/briar/android/AndroidModule.java +++ b/briar-android/src/net/sf/briar/android/AndroidModule.java @@ -1,5 +1,6 @@ package net.sf.briar.android; +import net.sf.briar.android.invitation.AddContactActivity; import net.sf.briar.api.android.AndroidExecutor; import net.sf.briar.api.android.BundleEncrypter; import net.sf.briar.api.android.ReferenceManager; @@ -16,5 +17,6 @@ public class AndroidModule extends AbstractModule { Singleton.class); bind(ReferenceManager.class).to(ReferenceManagerImpl.class).in( Singleton.class); + requestStaticInjection(AddContactActivity.class); } } diff --git a/briar-android/src/net/sf/briar/android/BundleEncrypterImpl.java b/briar-android/src/net/sf/briar/android/BundleEncrypterImpl.java index ce8f9912d75cdb9dd70330b4c6fbbebb9d719b2e..68305ffe6ce025510f8e58c422674f633ecfbf32 100644 --- a/briar-android/src/net/sf/briar/android/BundleEncrypterImpl.java +++ b/briar-android/src/net/sf/briar/android/BundleEncrypterImpl.java @@ -1,10 +1,12 @@ package net.sf.briar.android; +import static java.util.logging.Level.INFO; import static javax.crypto.Cipher.DECRYPT_MODE; import static javax.crypto.Cipher.ENCRYPT_MODE; import java.security.GeneralSecurityException; import java.security.SecureRandom; +import java.util.logging.Logger; import net.sf.briar.api.android.BundleEncrypter; import net.sf.briar.api.crypto.AuthenticatedCipher; @@ -19,6 +21,9 @@ import com.google.inject.Inject; // This class is not thread-safe class BundleEncrypterImpl implements BundleEncrypter { + private static final Logger LOG = + Logger.getLogger(BundleEncrypterImpl.class.getName()); + private final AuthenticatedCipher cipher; private final SecureRandom random; private final ErasableKey key; @@ -40,7 +45,11 @@ class BundleEncrypterImpl implements BundleEncrypter { b.writeToParcel(p, 0); byte[] plaintext = p.marshall(); p.recycle(); - // Encrypt the byte array using the storage key and a random IV + if(LOG.isLoggable(INFO)) { + LOG.info("Marshalled " + b.size() + " mappings, " + + plaintext.length + " plaintext bytes"); + } + // Encrypt the byte array using a random IV byte[] iv = new byte[blockSize]; random.nextBytes(iv); byte[] ciphertext = new byte[plaintext.length + macLength]; @@ -66,7 +75,7 @@ class BundleEncrypterImpl implements BundleEncrypter { byte[] ciphertext = b.getByteArray("net.sf.briar.CIPHERTEXT"); if(ciphertext == null) throw new IllegalArgumentException(); if(ciphertext.length < macLength) throw new IllegalArgumentException(); - // Decrypt the ciphertext using the storage key and the IV + // Decrypt the ciphertext using the IV byte[] plaintext = new byte[ciphertext.length - macLength]; try { cipher.init(DECRYPT_MODE, key, iv, null); @@ -78,12 +87,14 @@ class BundleEncrypterImpl implements BundleEncrypter { Parcel p = Parcel.obtain(); p.unmarshall(plaintext, 0, plaintext.length); ByteUtils.erase(plaintext); - // Replace the IV and the ciphertext with the plaintext contents - b.remove("net.sf.briar.IV"); - b.remove("net.sf.briar.CIPHERTEXT"); + // Restore the plaintext contents p.setDataPosition(0); b.readFromParcel(p); p.recycle(); + if(LOG.isLoggable(INFO)) { + LOG.info("Unmarshalled " + (b.size() - 2) + " mappings, " + + plaintext.length + " plaintext bytes"); + } return true; } } diff --git a/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java b/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java index 5de5df339ecced46fadd2d55addad3bd1c380e71..4b25d2a8949507fde50c1656a256a74ca5f5e8fd 100644 --- a/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java +++ b/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java @@ -19,6 +19,7 @@ import roboguice.activity.RoboActivity; import android.os.Bundle; import com.google.inject.Inject; +import com.google.inject.Provider; public class AddContactActivity extends RoboActivity implements InvitationListener { @@ -26,12 +27,17 @@ implements InvitationListener { private static final Logger LOG = Logger.getLogger(AddContactActivity.class.getName()); + // This allows us to access bundleEncrypter before calling super.onCreate() + @Inject private static Provider<BundleEncrypter> bundleEncrypterProvider; + + private final BundleEncrypter bundleEncrypter = + bundleEncrypterProvider.get(); + @Inject private CryptoComponent crypto; @Inject private DatabaseComponent db; @Inject @DatabaseExecutor private Executor dbExecutor; @Inject private InvitationTaskFactory invitationTaskFactory; @Inject private ReferenceManager referenceManager; - @Inject private BundleEncrypter bundleEncrypter; // All of the following must be accessed on the UI thread private AddContactView view = null; @@ -47,13 +53,13 @@ implements InvitationListener { @Override public void onCreate(Bundle state) { - super.onCreate(state); - if(state != null && !bundleEncrypter.decrypt(state)) state = null; - if(state == null) { - // This is a new activity + if(state == null || !bundleEncrypter.decrypt(state)) { + // This is a new activity or the process has restarted + super.onCreate(null); setView(new NetworkSetupView(this)); } else { // Restore the activity's state + super.onCreate(state); networkName = state.getString("net.sf.briar.NETWORK_NAME"); useBluetooth = state.getBoolean("net.sf.briar.USE_BLUETOOTH"); taskHandle = state.getLong("net.sf.briar.TASK_HANDLE", -1); @@ -114,6 +120,12 @@ implements InvitationListener { } } + @Override + public void onRestoreInstanceState(Bundle state) { + if(bundleEncrypter.decrypt(state)) + super.onRestoreInstanceState(state); + } + @Override public void onResume() { super.onResume(); @@ -123,16 +135,14 @@ implements InvitationListener { @Override public void onSaveInstanceState(Bundle state) { super.onSaveInstanceState(state); - Bundle b = new Bundle(); - b.putString("net.sf.briar.NETWORK_NAME", networkName); - b.putBoolean("net.sf.briar.USE_BLUETOOTH", useBluetooth); - b.putInt("net.sf.briar.LOCAL_CODE", localInvitationCode); - b.putInt("net.sf.briar.REMOTE_CODE", remoteInvitationCode); - b.putBoolean("net.sf.briar.FAILED", connectionFailed); - b.putBoolean("net.sf.briar.MATCHED", localMatched && remoteMatched); - if(task != null) b.putLong("net.sf.briar.TASK_HANDLE", taskHandle); - bundleEncrypter.encrypt(b); - state.putAll(b); + state.putString("net.sf.briar.NETWORK_NAME", networkName); + state.putBoolean("net.sf.briar.USE_BLUETOOTH", useBluetooth); + state.putInt("net.sf.briar.LOCAL_CODE", localInvitationCode); + state.putInt("net.sf.briar.REMOTE_CODE", remoteInvitationCode); + state.putBoolean("net.sf.briar.FAILED", connectionFailed); + state.putBoolean("net.sf.briar.MATCHED", localMatched && remoteMatched); + if(task != null) state.putLong("net.sf.briar.TASK_HANDLE", taskHandle); + bundleEncrypter.encrypt(state); } @Override