From 7439e5579f54f1158af76423124eb62ac29cf948 Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Wed, 5 Jun 2019 11:23:56 +0100 Subject: [PATCH] Let plugins know if we're Alice or Bob. --- .../api/plugin/duplex/DuplexPlugin.java | 2 +- .../plugin/bluetooth/BluetoothPlugin.java | 2 +- .../bramble/plugin/tcp/TcpPlugin.java | 2 +- .../bramble/plugin/tor/TorPlugin.java | 2 +- .../rendezvous/RendezvousPollerImpl.java | 62 ++++++++++++------- .../rendezvous/RendezvousPollerImplTest.java | 20 +++++- .../bramble/plugin/modem/ModemPlugin.java | 2 +- 7 files changed, 60 insertions(+), 32 deletions(-) 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 bc19732431..ce0e5787e7 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 58d06c52e1..0dec35bc5d 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<SS> 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 3529c58385..4ca15d0b98 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 ec523b9503..76d8f6109a 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 421d216fff..b7d355548a 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<TransportId, PluginState> pluginStates = new HashMap<>(); - private final Map<PendingContactId, SecretKey> rendezvousKeys = + private final Map<PendingContactId, CryptoState> 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<Pair<TransportProperties, ConnectionHandler>> properties = new ArrayList<>(); for (Entry<PendingContactId, RendezvousEndpoint> 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<PendingContactId, RendezvousEndpoint> endpoints = new HashMap<>(); - for (Entry<PendingContactId, SecretKey> e : rendezvousKeys.entrySet()) { + for (Entry<PendingContactId, CryptoState> 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 d88ff47d39..92af0f780e 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 21bef9284a..16a0d0f31f 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(); } -- GitLab