diff --git a/briar-core/src/net/sf/briar/transport/KeyManagerImpl.java b/briar-core/src/net/sf/briar/transport/KeyManagerImpl.java index 409ca79fa72ba23d76e7b882b3db266b6be27135..bf5eae2c7651758cf41bc0d7a04a469957ddd6fa 100644 --- a/briar-core/src/net/sf/briar/transport/KeyManagerImpl.java +++ b/briar-core/src/net/sf/briar/transport/KeyManagerImpl.java @@ -217,6 +217,7 @@ class KeyManagerImpl extends TimerTask implements KeyManager, DatabaseListener { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); return null; } + // Clone the secret - the original will be erased byte[] secret = s.getSecret().clone(); return new ConnectionContext(c, t, secret, connection, s.getAlice()); } diff --git a/briar-core/src/net/sf/briar/transport/TransportConnectionRecogniser.java b/briar-core/src/net/sf/briar/transport/TransportConnectionRecogniser.java index a827641d812babd5a72a91bf76c59d0d831c2f9c..9b9c177eded603caa8e03f04a212c31fe87e084e 100644 --- a/briar-core/src/net/sf/briar/transport/TransportConnectionRecogniser.java +++ b/briar-core/src/net/sf/briar/transport/TransportConnectionRecogniser.java @@ -18,7 +18,6 @@ import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DbException; import net.sf.briar.api.transport.ConnectionContext; import net.sf.briar.api.transport.TemporarySecret; -import net.sf.briar.util.ByteUtils; // FIXME: Don't make alien calls with a lock held /** A connection recogniser for a specific transport. */ @@ -41,46 +40,37 @@ class TransportConnectionRecogniser { synchronized ConnectionContext acceptConnection(byte[] tag) throws DbException { - TagContext tctx = tagMap.remove(new Bytes(tag)); - if(tctx == null) return null; // The tag was not expected - ConnectionWindow window = tctx.window; - ConnectionContext ctx = tctx.context; - long period = tctx.period; - ContactId contactId = ctx.getContactId(); - byte[] secret = ctx.getSecret(); - long connection = ctx.getConnectionNumber(); - boolean alice = ctx.getAlice(); + TagContext t = tagMap.remove(new Bytes(tag)); + if(t == null) return null; // The tag was not expected // Update the connection window and the expected tags Cipher cipher = crypto.getTagCipher(); - ErasableKey key = crypto.deriveTagKey(secret, !alice); - for(long connection1 : window.setSeen(connection)) { + ErasableKey key = crypto.deriveTagKey(t.secret, !t.alice); + for(long connection : t.window.setSeen(t.connection)) { byte[] tag1 = new byte[TAG_LENGTH]; - crypto.encodeTag(tag1, cipher, key, connection1); - if(connection1 < connection) { + crypto.encodeTag(tag1, cipher, key, connection); + if(connection < t.connection) { TagContext removed = tagMap.remove(new Bytes(tag1)); assert removed != null; - ByteUtils.erase(removed.context.getSecret()); } else { - ConnectionContext ctx1 = new ConnectionContext(contactId, - transportId, secret.clone(), connection1, alice); - TagContext tctx1 = new TagContext(window, ctx1, period); - TagContext duplicate = tagMap.put(new Bytes(tag1), tctx1); + TagContext added = new TagContext(t, connection); + TagContext duplicate = tagMap.put(new Bytes(tag1), added); assert duplicate == null; } } key.erase(); // Store the updated connection window in the DB - long centre = window.getCentre(); - byte[] bitmap = window.getBitmap(); - db.setConnectionWindow(contactId, transportId, period, centre, bitmap); - return ctx; + db.setConnectionWindow(t.contactId, transportId, t.period, + t.window.getCentre(), t.window.getBitmap()); + // Clone the secret - the key manager will erase the original + return new ConnectionContext(t.contactId, transportId, + t.secret.clone(), t.connection, t.alice); } synchronized void addSecret(TemporarySecret s) { ContactId contactId = s.getContactId(); + boolean alice = s.getAlice(); long period = s.getPeriod(); byte[] secret = s.getSecret(); - boolean alice = s.getAlice(); long centre = s.getWindowCentre(); byte[] bitmap = s.getWindowBitmap(); // Create the connection window and the expected tags @@ -90,66 +80,73 @@ class TransportConnectionRecogniser { for(long connection : window.getUnseen()) { byte[] tag = new byte[TAG_LENGTH]; crypto.encodeTag(tag, cipher, key, connection); - ConnectionContext ctx = new ConnectionContext(contactId, - transportId, secret.clone(), connection, alice); - TagContext tctx = new TagContext(window, ctx, period); - TagContext duplicate = tagMap.put(new Bytes(tag), tctx); + TagContext added = new TagContext(contactId, alice, period, + secret, window, connection); + TagContext duplicate = tagMap.put(new Bytes(tag), added); assert duplicate == null; } key.erase(); - // Create a removal context to remove the window later - RemovalContext rctx = new RemovalContext(window, secret, alice); - removalMap.put(new RemovalKey(contactId, period), rctx); + // Create a removal context to remove the window and the tags later + RemovalContext r = new RemovalContext(window, secret, alice); + removalMap.put(new RemovalKey(contactId, period), r); } synchronized void removeSecret(ContactId contactId, long period) { - RemovalKey rk = new RemovalKey(contactId, period); - RemovalContext rctx = removalMap.remove(rk); - if(rctx == null) throw new IllegalArgumentException(); - removeSecret(rctx); + RemovalKey k = new RemovalKey(contactId, period); + RemovalContext removed = removalMap.remove(k); + if(removed == null) throw new IllegalArgumentException(); + removeSecret(removed); } // Locking: this - private void removeSecret(RemovalContext rctx) { + private void removeSecret(RemovalContext r) { // Remove the expected tags Cipher cipher = crypto.getTagCipher(); - ErasableKey key = crypto.deriveTagKey(rctx.secret, !rctx.alice); + ErasableKey key = crypto.deriveTagKey(r.secret, !r.alice); byte[] tag = new byte[TAG_LENGTH]; - for(long connection : rctx.window.getUnseen()) { + for(long connection : r.window.getUnseen()) { crypto.encodeTag(tag, cipher, key, connection); TagContext removed = tagMap.remove(new Bytes(tag)); assert removed != null; - ByteUtils.erase(removed.context.getSecret()); } key.erase(); - ByteUtils.erase(rctx.secret); } synchronized void removeSecrets(ContactId c) { Collection<RemovalKey> keysToRemove = new ArrayList<RemovalKey>(); - for(RemovalKey k : removalMap.keySet()) { + for(RemovalKey k : removalMap.keySet()) if(k.contactId.equals(c)) keysToRemove.add(k); - } for(RemovalKey k : keysToRemove) removeSecret(k.contactId, k.period); } synchronized void removeSecrets() { - for(RemovalContext rctx : removalMap.values()) removeSecret(rctx); + for(RemovalContext r : removalMap.values()) removeSecret(r); assert tagMap.isEmpty(); removalMap.clear(); } private static class TagContext { - private final ConnectionWindow window; - private final ConnectionContext context; + private final ContactId contactId; + private final boolean alice; private final long period; + private final byte[] secret; + private final ConnectionWindow window; + private final long connection; - private TagContext(ConnectionWindow window, ConnectionContext context, - long period) { - this.window = window; - this.context = context; + private TagContext(ContactId contactId, boolean alice, long period, + byte[] secret, ConnectionWindow window, long connection) { + this.contactId = contactId; + this.alice = alice; this.period = period; + this.secret = secret; + this.window = window; + this.connection = connection; + } + + private TagContext(TagContext t, long connection) { + this(t.contactId, t.alice, t.period, t.secret, t.window, + connection); } } diff --git a/briar-tests/src/net/sf/briar/transport/TransportConnectionRecogniserTest.java b/briar-tests/src/net/sf/briar/transport/TransportConnectionRecogniserTest.java index fe6bd2cf567889d179adaf94977c3038ca286a20..6f2cae4125aa748723f12e5c70d15cd91df8ebfe 100644 --- a/briar-tests/src/net/sf/briar/transport/TransportConnectionRecogniserTest.java +++ b/briar-tests/src/net/sf/briar/transport/TransportConnectionRecogniserTest.java @@ -72,8 +72,6 @@ public class TransportConnectionRecogniserTest extends BriarTestCase { new TransportConnectionRecogniser(crypto, db, transportId); recogniser.addSecret(s); recogniser.removeSecret(contactId, 0); - // The secret should have been erased - assertArrayEquals(new byte[32], secret); context.assertIsSatisfied(); }