diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPlugin.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPlugin.java index bc1973243..ce0e5787e 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPlugin.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPlugin.java @@ -57,5 +57,5 @@ public interface DuplexPlugin extends Plugin { */ @Nullable RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k, - ConnectionHandler incoming); + boolean alice, ConnectionHandler incoming); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java index 58d06c52e..0dec35bc5 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java @@ -399,7 +399,7 @@ abstract class BluetoothPlugin implements DuplexPlugin, EventListener { @Override public RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k, - ConnectionHandler incoming) { + boolean alice, ConnectionHandler incoming) { throw new UnsupportedOperationException(); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java index 3529c5838..4ca15d0b9 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java @@ -310,7 +310,7 @@ abstract class TcpPlugin implements DuplexPlugin { @Override public RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k, - ConnectionHandler incoming) { + boolean alice, ConnectionHandler incoming) { throw new UnsupportedOperationException(); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java index ec523b950..76d8f6109 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java @@ -614,7 +614,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { @Override public RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k, - ConnectionHandler incoming) { + boolean alice, ConnectionHandler incoming) { throw new UnsupportedOperationException(); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/rendezvous/RendezvousPollerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/rendezvous/RendezvousPollerImpl.java index 421d216ff..b7d355548 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/rendezvous/RendezvousPollerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/rendezvous/RendezvousPollerImpl.java @@ -83,7 +83,7 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { private final Executor worker; // The following fields are only accessed on the worker private final Map pluginStates = new HashMap<>(); - private final Map rendezvousKeys = + private final Map cryptoStates = new HashMap<>(); @Nullable private KeyPair handshakeKeyPair = null; @@ -153,12 +153,15 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { .deriveStaticMasterKey(p.getPublicKey(), handshakeKeyPair); SecretKey rendezvousKey = rendezvousCrypto .deriveRendezvousKey(staticMasterKey); - requireNull(rendezvousKeys.put(p.getId(), rendezvousKey)); - for (PluginState state : pluginStates.values()) { + boolean alice = transportCrypto + .isAlice(p.getPublicKey(), handshakeKeyPair); + CryptoState cs = new CryptoState(rendezvousKey, alice); + requireNull(cryptoStates.put(p.getId(), cs)); + for (PluginState ps : pluginStates.values()) { RendezvousEndpoint endpoint = - createEndpoint(state.plugin, p.getId(), rendezvousKey); + createEndpoint(ps.plugin, p.getId(), cs); if (endpoint != null) - requireNull(state.endpoints.put(p.getId(), endpoint)); + requireNull(ps.endpoints.put(p.getId(), endpoint)); } } catch (DbException | GeneralSecurityException e) { logException(LOG, WARNING, e); @@ -179,9 +182,9 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { // Worker private boolean removePendingContact(PendingContactId p) { // We can come here twice if a pending contact fails and is then removed - if (rendezvousKeys.remove(p) == null) return false; - for (PluginState state : pluginStates.values()) { - RendezvousEndpoint endpoint = state.endpoints.remove(p); + if (cryptoStates.remove(p) == null) return false; + for (PluginState ps : pluginStates.values()) { + RendezvousEndpoint endpoint = ps.endpoints.remove(p); if (endpoint != null) tryToClose(endpoint, LOG, INFO); } return true; @@ -189,33 +192,33 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { @Nullable private RendezvousEndpoint createEndpoint(DuplexPlugin plugin, - PendingContactId p, SecretKey rendezvousKey) { + PendingContactId p, CryptoState cs) { TransportId t = plugin.getId(); KeyMaterialSource k = - rendezvousCrypto.createKeyMaterialSource(rendezvousKey, t); + rendezvousCrypto.createKeyMaterialSource(cs.rendezvousKey, t); Handler h = new Handler(p, t, true); - return plugin.createRendezvousEndpoint(k, h); + return plugin.createRendezvousEndpoint(k, cs.alice, h); } @Scheduler private void poll() { worker.execute(() -> { - for (PluginState state : pluginStates.values()) poll(state); + for (PluginState ps : pluginStates.values()) poll(ps); }); } // Worker - private void poll(PluginState state) { + private void poll(PluginState ps) { List> properties = new ArrayList<>(); for (Entry e : - state.endpoints.entrySet()) { + ps.endpoints.entrySet()) { TransportProperties props = e.getValue().getRemoteTransportProperties(); - Handler h = new Handler(e.getKey(), state.plugin.getId(), false); + Handler h = new Handler(e.getKey(), ps.plugin.getId(), false); properties.add(new Pair<>(props, h)); } - state.plugin.poll(properties); + ps.plugin.poll(properties); } @Override @@ -249,13 +252,13 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { // Worker private void poll(PendingContactId p) { - for (PluginState state : pluginStates.values()) { - RendezvousEndpoint endpoint = state.endpoints.get(p); + for (PluginState ps : pluginStates.values()) { + RendezvousEndpoint endpoint = ps.endpoints.get(p); if (endpoint != null) { TransportProperties props = endpoint.getRemoteTransportProperties(); - Handler h = new Handler(p, state.plugin.getId(), false); - state.plugin.poll(singletonList(new Pair<>(props, h))); + Handler h = new Handler(p, ps.plugin.getId(), false); + ps.plugin.poll(singletonList(new Pair<>(props, h))); } } } @@ -279,7 +282,7 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { private void addTransport(DuplexPlugin plugin) { TransportId t = plugin.getId(); Map endpoints = new HashMap<>(); - for (Entry e : rendezvousKeys.entrySet()) { + for (Entry e : cryptoStates.entrySet()) { RendezvousEndpoint endpoint = createEndpoint(plugin, e.getKey(), e.getValue()); if (endpoint != null) endpoints.put(e.getKey(), endpoint); @@ -294,9 +297,9 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { // Worker private void removeTransport(TransportId t) { - PluginState state = pluginStates.remove(t); - if (state != null) { - for (RendezvousEndpoint endpoint : state.endpoints.values()) { + PluginState ps = pluginStates.remove(t); + if (ps != null) { + for (RendezvousEndpoint endpoint : ps.endpoints.values()) { tryToClose(endpoint, LOG, INFO); } } @@ -314,6 +317,17 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { } } + private static class CryptoState { + + private final SecretKey rendezvousKey; + private final boolean alice; + + private CryptoState(SecretKey rendezvousKey, boolean alice) { + this.rendezvousKey = rendezvousKey; + this.alice = alice; + } + } + private class Handler implements ConnectionHandler { private final PendingContactId pendingContactId; diff --git a/bramble-core/src/test/java/org/briarproject/bramble/rendezvous/RendezvousPollerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/rendezvous/RendezvousPollerImplTest.java index d88ff47d3..92af0f780 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/rendezvous/RendezvousPollerImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/rendezvous/RendezvousPollerImplTest.java @@ -30,6 +30,7 @@ import org.jmock.Expectations; import org.junit.Before; import org.junit.Test; +import java.util.Random; import java.util.concurrent.Executor; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicReference; @@ -79,6 +80,7 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { private final TransportId transportId = getTransportId(); private final TransportProperties transportProperties = getTransportProperties(3); + private final boolean alice = new Random().nextBoolean(); private RendezvousPollerImpl rendezvousPoller; @@ -122,6 +124,9 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { will(returnValue(staticMasterKey)); oneOf(rendezvousCrypto).deriveRendezvousKey(staticMasterKey); will(returnValue(rendezvousKey)); + oneOf(transportCrypto).isAlice(pendingContact.getPublicKey(), + handshakeKeyPair); + will(returnValue(alice)); }}); rendezvousPoller.startService(); @@ -182,11 +187,14 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { will(returnValue(staticMasterKey)); oneOf(rendezvousCrypto).deriveRendezvousKey(staticMasterKey); will(returnValue(rendezvousKey)); + oneOf(transportCrypto).isAlice(pendingContact.getPublicKey(), + handshakeKeyPair); + will(returnValue(alice)); oneOf(rendezvousCrypto).createKeyMaterialSource(rendezvousKey, transportId); will(returnValue(keyMaterialSource)); oneOf(plugin).createRendezvousEndpoint(with(keyMaterialSource), - with(any(ConnectionHandler.class))); + with(alice), with(any(ConnectionHandler.class))); will(returnValue(rendezvousEndpoint)); // Poll newly added pending contact oneOf(rendezvousEndpoint).getRemoteTransportProperties(); @@ -250,11 +258,14 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { will(returnValue(staticMasterKey)); oneOf(rendezvousCrypto).deriveRendezvousKey(staticMasterKey); will(returnValue(rendezvousKey)); + oneOf(transportCrypto).isAlice(pendingContact.getPublicKey(), + handshakeKeyPair); + will(returnValue(alice)); oneOf(rendezvousCrypto).createKeyMaterialSource(rendezvousKey, transportId); will(returnValue(keyMaterialSource)); oneOf(plugin).createRendezvousEndpoint(with(keyMaterialSource), - with(any(ConnectionHandler.class))); + with(alice), with(any(ConnectionHandler.class))); will(returnValue(rendezvousEndpoint)); // Poll newly added pending contact oneOf(rendezvousEndpoint).getRemoteTransportProperties(); @@ -305,6 +316,9 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { will(returnValue(staticMasterKey)); oneOf(rendezvousCrypto).deriveRendezvousKey(staticMasterKey); will(returnValue(rendezvousKey)); + oneOf(transportCrypto).isAlice(pendingContact.getPublicKey(), + handshakeKeyPair); + will(returnValue(alice)); }}); rendezvousPoller.eventOccurred( @@ -323,7 +337,7 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { transportId); will(returnValue(keyMaterialSource)); oneOf(plugin).createRendezvousEndpoint(with(keyMaterialSource), - with(any(ConnectionHandler.class))); + with(alice), with(any(ConnectionHandler.class))); will(returnValue(rendezvousEndpoint)); }}); diff --git a/bramble-java/src/main/java/org/briarproject/bramble/plugin/modem/ModemPlugin.java b/bramble-java/src/main/java/org/briarproject/bramble/plugin/modem/ModemPlugin.java index 21bef9284..16a0d0f31 100644 --- a/bramble-java/src/main/java/org/briarproject/bramble/plugin/modem/ModemPlugin.java +++ b/bramble-java/src/main/java/org/briarproject/bramble/plugin/modem/ModemPlugin.java @@ -193,7 +193,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback { @Override public RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k, - ConnectionHandler incoming) { + boolean alice, ConnectionHandler incoming) { throw new UnsupportedOperationException(); }